home *** CD-ROM | disk | FTP | other *** search
/ Super Shareware Collection / Super Shareware Collection.iso / os_2 / memsz220.zip / MEMSIZE.CPP < prev    next >
C/C++ Source or Header  |  1994-02-07  |  112KB  |  3,313 lines

  1. /***************************************************************** MEMSIZE.CC
  2.  *                                        *
  3.  * System Resources Monitor                            *
  4.  *                                        *
  5.  * (C) Copyright 1991-1993 by Richard W. Papo.                    *
  6.  *                                        *
  7.  * This is 'FreeWare'.    As such, it may be copied and distributed        *
  8.  * freely.  If you want to use part of it in your own program, please        *
  9.  * give credit where credit is due.  If you want to change the            *
  10.  * program, please refer the change request to me or send me the        *
  11.  * modified source code.  I can be reached at CompuServe 72607,3111.        *
  12.  *                                        *
  13.  ****************************************************************************/
  14.  
  15. //
  16. // Things to do:
  17. //
  18. //   (1) Validate memory statistics against OS20MEMU.
  19. //
  20. //   (2) Provide an item to serve as a button to cause a secondary
  21. //     drive status window to be displayed.
  22. //
  23. //   (3) Make file system name display optional.
  24. //
  25. //   (4) Make drive percentage utilization available as an option.
  26. //
  27.  
  28. #define INCL_BASE
  29. #define INCL_PM
  30. #include <os2.h>
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35.  
  36. #include "debug.h"
  37. #include "support.h"
  38.  
  39. #include "about.h"
  40. #include "config.h"
  41. #include "process.h"
  42. #include "profile.h"
  43. #include "restring.h"
  44.  
  45. #include "items.h"
  46.  
  47. #include "memsize.h"
  48.  
  49. #define STATIC static
  50.  
  51.  
  52. /****************************************************************************
  53.  *                                        *
  54.  *             Definitions & Declarations                *
  55.  *                                        *
  56.  ****************************************************************************/
  57.  
  58.   // Constants
  59.  
  60. #define PROGRAM_NAME       "MEMSIZE"
  61. #define CLASS_NAME        PROGRAM_NAME
  62.  
  63. #define WM_REFRESH        (WM_USER)
  64.  
  65. #define MAX_DRIVES      (26)
  66. #define DRIVE_ERROR      (0xFFFFFFFFL)
  67.  
  68. enum
  69. {
  70.   ITEM_CLOCK,
  71.   ITEM_ELAPSEDTIME,
  72.   ITEM_MEMORYFREE,
  73.   ITEM_SWAPFILESIZE,
  74.   ITEM_SWAPDISKFREE,
  75.   ITEM_SPOOLFILESIZE,
  76.   ITEM_CPULOAD,
  77.   ITEM_TASKCOUNT,
  78.   ITEM_TOTALFREE,
  79.   ITEM_BASE_COUNT
  80. } ;
  81.  
  82.  
  83.   // Data Types
  84.  
  85. typedef struct          // Parameters saved to system.
  86. {
  87.   // The Display Item List - - -
  88.   Item         *Items [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  89.   int          ItemCount ;
  90.  
  91.   // Data required for the display item objects to function.
  92.   ULONG       IdleCount ;
  93.   ULONG       MaxCount ;
  94.   BYTE          SwapPath [_MAX_PATH] ;
  95.   ULONG       MinFree ;
  96.   PBYTE       SpoolPath ;
  97.   COUNTRYINFO      CountryInfo ;
  98.   ResourceString *Day ;
  99.   ResourceString *Days ;
  100.   ResourceString *DaysOfWeek ;
  101.   ResourceString *DriveError ;
  102.  
  103.   // Window size and location
  104.   SWP     Position ;
  105.   BOOL     fPosition ;
  106.  
  107.   // User Options
  108.   BOOL     HideControls ;
  109.   BOOL     fHideControls ;
  110.  
  111.   BOOL     Float ;
  112.   BOOL     fFloat ;
  113.  
  114.   USHORT TimerInterval ;
  115.   BOOL     fTimerInterval ;
  116.  
  117.   // Presentation Parameters
  118.   BYTE     FontNameSize [80] ;
  119.   BOOL     fFontNameSize ;
  120.  
  121.   COLOR  BackColor ;
  122.   BOOL     fBackColor ;
  123.  
  124.   COLOR  TextColor ;
  125.   BOOL     fTextColor ;
  126. }
  127. PROFILE, *PPROFILE ;
  128.  
  129. typedef struct        // Data structure for window.
  130. {
  131.   HAB         Anchor ;
  132.   HMODULE     Library ;
  133.   HINI           ProfileHandle ;
  134.  
  135.   ULONG      IdleCounter ;
  136.   TID         IdleLoopTID ;
  137.   TID         MonitorLoopTID ;
  138.  
  139.   PROFILE     Profile ;
  140.  
  141.   HWND           hwndTitleBar ;
  142.   HWND           hwndSysMenu ;
  143.   HWND         hwndMinMax ;
  144.  
  145.   ULONG      Drives ;
  146.  
  147.   long         Width ;
  148.   long         Height ;
  149.  
  150. }
  151. DATA, *PDATA ;
  152.  
  153. typedef struct
  154. {
  155.   HAB Anchor ;
  156.   HMODULE Library ;
  157.   HINI ProfileHandle ;
  158. }
  159. PARMS, *PPARMS ;
  160.  
  161. typedef struct
  162. {
  163.   volatile PULONG Counter ;
  164.   PUSHORT Interval ;
  165.   HWND Owner ;
  166. }
  167. MONITOR_PARMS, *PMONITOR_PARMS ;
  168.  
  169.  
  170.   // Function Prototypes
  171.  
  172. extern INT main ( INT argc, PCHAR argv[] ) ;
  173.  
  174. STATIC MRESULT EXPENTRY MessageProcessor
  175. (
  176.   HWND hwnd,
  177.   USHORT msg,
  178.   MPARAM mp1,
  179.   MPARAM mp2
  180. ) ;
  181.  
  182. STATIC METHODFUNCTION Create ;
  183. STATIC METHODFUNCTION Destroy ;
  184. STATIC METHODFUNCTION Size ;
  185. STATIC METHODFUNCTION SaveApplication ;
  186. STATIC METHODFUNCTION Paint ;
  187. STATIC METHODFUNCTION Command ;
  188. STATIC METHODFUNCTION ResetDefaults ;
  189. STATIC METHODFUNCTION HideControlsCmd ;
  190. STATIC METHODFUNCTION Configure ;
  191. STATIC METHODFUNCTION About ;
  192. STATIC METHODFUNCTION ButtonDown ;
  193. STATIC METHODFUNCTION ButtonDblClick ;
  194. STATIC METHODFUNCTION PresParamChanged ;
  195. STATIC METHODFUNCTION SysColorChange ;
  196. STATIC METHODFUNCTION QueryKeysHelp ;
  197. STATIC METHODFUNCTION HelpError ;
  198. STATIC METHODFUNCTION ExtHelpUndefined ;
  199. STATIC METHODFUNCTION HelpSubitemNotFound ;
  200. STATIC METHODFUNCTION Refresh ;
  201.  
  202. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile ) ;
  203. STATIC VOID PutProfile ( HINI ProfileHandle, PPROFILE Profile ) ;
  204.  
  205. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
  206.  
  207. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile ) ;
  208.  
  209. STATIC void HideControls
  210. (
  211.   BOOL fHide,
  212.   HWND hwndFrame,
  213.   HWND hwndSysMenu,
  214.   HWND hwndTitleBar,
  215.   HWND hwndMinMax
  216. ) ;
  217.  
  218. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) ;
  219.  
  220. STATIC VOID APIENTRY MonitorLoopThread ( ULONG Parameter ) ;
  221.  
  222. STATIC VOID UpdateDriveList
  223. (
  224.   HAB Anchor,
  225.   HMODULE Library,
  226.   HINI ProfileHandle,
  227.   PPROFILE Profile,
  228.   ULONG OldDrives,
  229.   ULONG NewDrives
  230. ) ;
  231.  
  232. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem ) ;
  233.  
  234. STATIC ULONG CalibrateLoadMeter ( VOID ) ;
  235.  
  236. STATIC VOID APIENTRY CounterThread ( ULONG Parameter ) ;
  237.  
  238. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance ) ;
  239.  
  240.  
  241. /****************************************************************************
  242.  *                                        *
  243.  *    Program Mainline                            *
  244.  *                                        *
  245.  ****************************************************************************/
  246.  
  247. extern INT main ( INT argc, PCHAR argv[] )
  248. {
  249.  /***************************************************************************
  250.   * Initialize the process.                            *
  251.   ***************************************************************************/
  252.  
  253.   Process Proc ;
  254.  
  255.  /***************************************************************************
  256.   * Now WIN and GPI calls will work.  Open the language DLL.            *
  257.   ***************************************************************************/
  258.  
  259.   HMODULE Library ;
  260.   if ( DosLoadModule ( NULL, 0, (PSZ)PROGRAM_NAME, &Library ) )
  261.   {
  262.     Debug ( HWND_DESKTOP, "ERROR: Unable to load " PROGRAM_NAME ".DLL." ) ;
  263.     DosExit ( EXIT_PROCESS, 1 ) ;
  264.   }
  265.  
  266.  /***************************************************************************
  267.   * Get the program title.                                        *
  268.   ***************************************************************************/
  269.  
  270.   ResourceString Title ( Library, IDS_TITLE ) ;
  271.  
  272.  /***************************************************************************
  273.   * Decipher command-line parameters.                        *
  274.   ***************************************************************************/
  275.  
  276.   BOOL Reset = FALSE ;
  277.  
  278.   ResourceString ResetCommand ( Library, IDS_PARMS_RESET ) ;
  279.  
  280.   while ( --argc )
  281.   {
  282.     argv ++ ;
  283.  
  284.     WinUpper ( Proc.QueryAnchor(), NULL, NULL, (PSZ)*argv ) ;
  285.  
  286.     if ( *argv[0] == '?' )
  287.     {
  288.       ResourceString Message ( Library, IDS_PARAMETERLIST ) ;
  289.  
  290.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  291.     Title.Ptr(), 0, MB_ENTER | MB_NOICON ) ;
  292.  
  293.       DosExit ( EXIT_PROCESS, 1 ) ;
  294.     }
  295.  
  296.     if ( !strcmp ( *argv, (PCHAR)ResetCommand.Ptr() ) )
  297.     {
  298.       Reset = TRUE ;
  299.       continue ;
  300.     }
  301.  
  302.     {
  303.       ResourceString Format ( Library, IDS_ERROR_INVALIDPARM ) ;
  304.  
  305.       BYTE Message [200] ;
  306.       sprintf ( (PCHAR)Message, (PCHAR)Format.Ptr(), *argv ) ;
  307.  
  308.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  309.     Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  310.  
  311.       DosExit ( EXIT_PROCESS, 1 ) ;
  312.     }
  313.   }
  314.  
  315.  /***************************************************************************
  316.   * Create the help instance.                            *
  317.   ***************************************************************************/
  318.  
  319.   HELPINIT HelpInit =
  320.   {
  321.     sizeof ( HELPINIT ),
  322.     0L,
  323.     NULL,
  324.     0,
  325.     0,
  326.     0,
  327.     0,
  328.     0,
  329.     NULL,
  330.     CMIC_HIDE_PANEL_ID,
  331.     PSZ ( PROGRAM_NAME ".HLP" )
  332.   } ;
  333.  
  334.   HelpInit.hmodHelpTableModule = HMODULE ( MAKEP ( 0xFFFF, ID_MAIN ) ) ;
  335.  
  336.   ResourceString HelpTitle ( Library, IDS_HELPTITLE ) ;
  337.  
  338.   HelpInit.pszHelpWindowTitle = HelpTitle.Ptr() ;
  339.  
  340.   HWND hwndHelp = WinCreateHelpInstance ( Proc.QueryAnchor(), &HelpInit ) ;
  341.  
  342.   if ( hwndHelp == NULL )
  343.   {
  344.     ResourceString Message ( Library, IDS_ERROR_WINCREATEHELPINSTANCE ) ;
  345.  
  346.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  347.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  348.   }
  349.  
  350.  /***************************************************************************
  351.   * Open/create the profile file.                                       *
  352.   ***************************************************************************/
  353.  
  354.   HINI ProfileHandle = OpenProfile ( PSZ(PROGRAM_NAME),
  355.     Proc.QueryAnchor(), Library, hwndHelp ) ;
  356.  
  357.   if ( ProfileHandle == NULL )
  358.   {
  359.     ResourceString Message ( Library, IDS_ERROR_PRFOPENPROFILE ) ;
  360.  
  361. //  Log ( "%s\r\n", Message.Ptr() ) ;
  362.  
  363.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  364.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  365.  
  366.     DosFreeModule ( Library ) ;
  367.     DosExit ( EXIT_PROCESS, 1 ) ;
  368.   }
  369.  
  370.  /***************************************************************************
  371.   * If we're going to reset the program's profile, do it now.               *
  372.   ***************************************************************************/
  373.  
  374.   if ( Reset )
  375.   {
  376.     PrfWriteProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  377.   }
  378.  
  379.  /***************************************************************************
  380.   * Create the frame window.                            *
  381.   ***************************************************************************/
  382.  
  383.   #pragma pack(2)
  384.   struct
  385.   {
  386.     USHORT Filler ;
  387.     USHORT cb ;
  388.     ULONG  flCreateFlags ;
  389.     USHORT hmodResources ;
  390.     USHORT idResources ;
  391.   }
  392.   fcdata ;
  393.   #pragma pack()
  394.  
  395.   fcdata.cb = sizeof(fcdata) - sizeof(fcdata.Filler) ;
  396.   fcdata.flCreateFlags =
  397.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  398.     FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE ;
  399.   fcdata.hmodResources = 0 ;
  400.   fcdata.idResources = ID_MAIN ;
  401.  
  402.   HWND hwndFrame = WinCreateWindow
  403.   (
  404.     HWND_DESKTOP,
  405.     WC_FRAME,
  406.     Title.Ptr(),
  407.     WS_ANIMATE,
  408.     0, 0, 0, 0,
  409.     HWND_DESKTOP,
  410.     HWND_TOP,
  411.     ID_MAIN,
  412.     &fcdata.cb,
  413.     NULL
  414.   ) ;
  415.  
  416.   if ( hwndFrame == NULL )
  417.   {
  418.     ResourceString Message ( Library, IDS_ERROR_WINCREATEFRAME ) ;
  419.  
  420.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  421.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  422.  
  423.     PrfCloseProfile ( ProfileHandle ) ;
  424.     DosFreeModule ( Library ) ;
  425.     DosExit ( EXIT_PROCESS, 1 ) ;
  426.   }
  427.  
  428.  /***************************************************************************
  429.   * Associate the help instance with the frame window.                *
  430.   ***************************************************************************/
  431.  
  432.   if ( hwndHelp )
  433.   {
  434.     WinAssociateHelpInstance ( hwndHelp, hwndFrame ) ;
  435.   }
  436.  
  437.  /***************************************************************************
  438.   * Register the window class.                            *
  439.   ***************************************************************************/
  440.  
  441.   if ( NOT WinRegisterClass ( Proc.QueryAnchor(), PSZ(CLASS_NAME),
  442.     PFNWP(MessageProcessor), CS_MOVENOTIFY, sizeof(PVOID) ) )
  443.   {
  444.     ResourceString Format ( Library, IDS_ERROR_WINREGISTERCLASS ) ;
  445.  
  446.     BYTE Message [200] ;
  447.     sprintf ( PCHAR(Message), PCHAR(Format.Ptr()), CLASS_NAME ) ;
  448.  
  449.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  450.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  451.  
  452.     PrfCloseProfile ( ProfileHandle ) ;
  453.     DosFreeModule ( Library ) ;
  454.     DosExit ( EXIT_PROCESS, 1 ) ;
  455.   }
  456.  
  457.  /***************************************************************************
  458.   * Create client window.  If this fails, destroy frame and return.        *
  459.   ***************************************************************************/
  460.  
  461.   PARMS Parms ;
  462.   Parms.Anchor = Proc.QueryAnchor() ;
  463.   Parms.Library = Library ;
  464.   Parms.ProfileHandle = ProfileHandle ;
  465.  
  466.   HWND hwndClient = WinCreateWindow
  467.   (
  468.     hwndFrame,
  469.     (PSZ)CLASS_NAME,
  470.     (PSZ)"",
  471.     0,
  472.     0, 0, 0, 0,
  473.     hwndFrame,
  474.     HWND_BOTTOM,
  475.     FID_CLIENT,
  476.     &Parms,
  477.     NULL
  478.   ) ;
  479.  
  480.   if ( hwndClient == NULL )
  481.   {
  482.     ResourceString Message ( Library, IDS_ERROR_WINCREATEWINDOW ) ;
  483.  
  484.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message.Ptr(),
  485.       Title.Ptr(), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  486.  
  487.     WinDestroyWindow ( hwndFrame ) ;
  488.     if ( hwndHelp )
  489.     {
  490.       WinDestroyHelpInstance ( hwndHelp ) ;
  491.     }
  492.     PrfCloseProfile ( ProfileHandle ) ;
  493.     DosFreeModule ( Library ) ;
  494.     DosExit ( EXIT_PROCESS, 1 ) ;
  495.   }
  496.  
  497.  /***************************************************************************
  498.   * Wait for and process messages to the window's queue.  Terminate         *
  499.   *   when the WM_QUIT message is received.                    *
  500.   ***************************************************************************/
  501.  
  502.   QMSG QueueMessage ;
  503.   while ( WinGetMsg ( Proc.QueryAnchor(), &QueueMessage, NULL, 0, 0 ) )
  504.   {
  505.     WinDispatchMsg ( Proc.QueryAnchor(), &QueueMessage ) ;
  506.   }
  507.  
  508.  /***************************************************************************
  509.   * Discard all that was requested of the system and terminate.         *
  510.   ***************************************************************************/
  511.  
  512.   WinDestroyWindow ( hwndFrame ) ;
  513.  
  514.   if ( hwndHelp )
  515.   {
  516.     WinDestroyHelpInstance ( hwndHelp ) ;
  517.   }
  518.  
  519.   PrfCloseProfile ( ProfileHandle ) ;
  520.  
  521.   DosFreeModule ( Library ) ;
  522.  
  523.   DosExit ( EXIT_PROCESS, 0 ) ;
  524. }
  525.  
  526. /****************************************************************************
  527.  *                                        *
  528.  *    Window Message Processor                        *
  529.  *                                        *
  530.  ****************************************************************************/
  531.  
  532. STATIC MRESULT EXPENTRY MessageProcessor
  533. (
  534.   HWND hwnd,
  535.   USHORT msg,
  536.   MPARAM mp1,
  537.   MPARAM mp2
  538. )
  539. {
  540.  /***************************************************************************
  541.   * Dispatch the message according to the method table and return the        *
  542.   *   result.  Any messages not defined above get handled by the system     *
  543.   *   default window processor.                         *
  544.   ***************************************************************************/
  545.  
  546.   static METHOD Methods [] =
  547.   {
  548.     { WM_CREATE,        Create            },
  549.     { WM_DESTROY,        Destroy         },
  550.     { WM_SIZE,            Size            },
  551.     { WM_MOVE,            Size            },
  552.     { WM_SAVEAPPLICATION,    SaveApplication     },
  553.     { WM_PAINT,         Paint            },
  554.     { WM_BUTTON1DOWN,        ButtonDown        },
  555.     { WM_BUTTON2DOWN,        ButtonDown        },
  556.     { WM_BUTTON1DBLCLK,     ButtonDblClick        },
  557.     { WM_BUTTON2DBLCLK,     ButtonDblClick        },
  558.     { WM_PRESPARAMCHANGED,    PresParamChanged    },
  559.     { WM_SYSCOLORCHANGE,    SysColorChange        },
  560.     { WM_COMMAND,        Command         },
  561.     { HM_QUERY_KEYS_HELP,    QueryKeysHelp        },
  562.     { HM_ERROR,         HelpError        },
  563.     { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  564.     { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound },
  565.     { WM_REFRESH,        Refresh         }
  566.   } ;
  567.  
  568.   return ( DispatchMessage ( hwnd, msg, mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), WinDefWindowProc ) ) ;
  569. }
  570.  
  571. /****************************************************************************
  572.  *                                        *
  573.  *    Create the main window.                         *
  574.  *                                        *
  575.  ****************************************************************************/
  576.  
  577. STATIC MRESULT APIENTRY Create
  578. (
  579.   HWND hwnd,
  580.   USHORT msg,
  581.   MPARAM mp1,
  582.   MPARAM mp2
  583. )
  584. {
  585.  /***************************************************************************
  586.   * Allocate instance data.                            *
  587.   ***************************************************************************/
  588.  
  589.   PDATA Data = PDATA ( malloc ( sizeof(DATA) ) ) ;
  590.  
  591.   memset ( Data, 0, sizeof(DATA) ) ;
  592.  
  593.   WinSetWindowPtr ( hwnd, QWL_USER, Data ) ;
  594.  
  595.  /***************************************************************************
  596.   * Grab any parameters from the WM_CREATE message.                *
  597.   ***************************************************************************/
  598.  
  599.   PPARMS Parms = (PPARMS) PVOIDFROMMP ( mp1 ) ;
  600.  
  601.   Data->Anchor = Parms->Anchor ;
  602.   Data->Library = Parms->Library ;
  603.   Data->ProfileHandle = Parms->ProfileHandle ;
  604.  
  605.  /***************************************************************************
  606.   * Get the current drive mask.                         *
  607.   ***************************************************************************/
  608.  
  609.   ULONG Drive ;
  610.   DosQueryCurrentDisk ( &Drive, &Data->Drives ) ;
  611.  
  612.  /***************************************************************************
  613.   * Initialize the global resource strings.                    *
  614.   ***************************************************************************/
  615.  
  616.   Data->Profile.Day       = new ResourceString ( Data->Library, IDS_DAY ) ;
  617.   Data->Profile.Days       = new ResourceString ( Data->Library, IDS_DAYS ) ;
  618.   Data->Profile.DaysOfWeek = new ResourceString ( Data->Library, IDS_DAYSOFWEEK ) ;
  619.   Data->Profile.DriveError = new ResourceString ( Data->Library, IDS_DRIVEERROR ) ;
  620.  
  621.  /***************************************************************************
  622.   * Get country information.                            *
  623.   ***************************************************************************/
  624.  
  625.   COUNTRYCODE CountryCode ;
  626.   ULONG Count ;
  627.   ULONG Status ;
  628.  
  629.   CountryCode.country = 0 ;
  630.   CountryCode.codepage = 0 ;
  631.  
  632.   Status = DosGetCtryInfo ( sizeof(Data->Profile.CountryInfo), &CountryCode,
  633.     &Data->Profile.CountryInfo, &Count ) ;
  634.   if ( Status )
  635.   {
  636.     BYTE Message [80] ;
  637.     WinLoadMessage ( Data->Anchor, Data->Library, IDS_ERROR_DOSGETCTRYINFO,
  638.       sizeof(Message), Message ) ;
  639.     Debug ( hwnd, (PCHAR)Message, Status ) ;
  640.     Data->Profile.CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  641.     Data->Profile.CountryInfo.fsTimeFmt = 0 ;
  642.     Data->Profile.CountryInfo.szDateSeparator[0] = '/' ;
  643.     Data->Profile.CountryInfo.szDateSeparator[1] = 0 ;
  644.     Data->Profile.CountryInfo.szTimeSeparator[0] = ':' ;
  645.     Data->Profile.CountryInfo.szTimeSeparator[1] = 0 ;
  646.     Data->Profile.CountryInfo.szThousandsSeparator[0] = ',' ;
  647.     Data->Profile.CountryInfo.szThousandsSeparator[1] = 0 ;
  648.   }
  649.  
  650.  /***************************************************************************
  651.   * Get the SWAPPATH statement from CONFIG.SYS.                 *
  652.   ***************************************************************************/
  653.  
  654.   PSZ Swappath = ScanSystemConfig ( Data->Anchor, (PSZ)"SWAPPATH" ) ;
  655.  
  656.   if ( Swappath == NULL )
  657.   {
  658.     Swappath = (PSZ) "C:\\OS2\\SYSTEM 0" ;
  659.   }
  660.  
  661.   sscanf ( (PCHAR)Swappath, "%s %li",
  662.     Data->Profile.SwapPath, &Data->Profile.MinFree ) ;
  663.  
  664.  /***************************************************************************
  665.   * Find out where the spool work directory is.                 *
  666.   ***************************************************************************/
  667.  
  668.   Data->Profile.SpoolPath = NULL ;
  669.  
  670.   ULONG Size ;
  671.   if ( PrfQueryProfileSize ( HINI_PROFILE, (PSZ)"PM_SPOOLER", (PSZ)"DIR", &Size ) )
  672.   {
  673.     Data->Profile.SpoolPath = PSZ ( malloc ( (int)Size ) ) ;
  674.  
  675.     if ( Data->Profile.SpoolPath )
  676.     {
  677.       if ( PrfQueryProfileData ( HINI_PROFILE, (PSZ)"PM_SPOOLER", (PSZ)"DIR", Data->Profile.SpoolPath, &Size ) )
  678.       {
  679.     PBYTE p = (PBYTE) strchr ( (PCHAR)Data->Profile.SpoolPath, ';' ) ;
  680.     if ( p )
  681.     {
  682.       *p = 0 ;
  683.     }
  684.       }
  685.       else
  686.       {
  687.     free ( Data->Profile.SpoolPath ) ;
  688.     Data->Profile.SpoolPath = NULL ;
  689.       }
  690.     }
  691.   }
  692.  
  693.  /***************************************************************************
  694.   * Calibrate the old-style load meter, if the high resolution timer's      *
  695.   *   available.                                *
  696.   ***************************************************************************/
  697.  
  698.   Data->Profile.MaxCount = CalibrateLoadMeter ( ) ;
  699.   Data->Profile.MaxCount = (ULONG) max ( 1L, Data->Profile.MaxCount ) ;
  700.  
  701.  /***************************************************************************
  702.   * Get profile data. Try the OS2.INI first, then try for private INI.      *
  703.   *   If obtained from OS2.INI, erase it afterwards.                        *
  704.   ***************************************************************************/
  705.  
  706.   if ( GetProfile ( Data->Anchor, Data->Library, HINI_USERPROFILE, &Data->Profile ) )
  707.   {
  708.     GetProfile ( Data->Anchor, Data->Library, Data->ProfileHandle, &Data->Profile ) ;
  709.   }
  710.   else
  711.   {
  712.     PrfWriteProfileData ( HINI_USERPROFILE, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  713.   }
  714.  
  715.  /***************************************************************************
  716.   * Get the frame handle.                            *
  717.   ***************************************************************************/
  718.  
  719.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  720.  
  721.  /***************************************************************************
  722.   * Get the control window handles.                        *
  723.   ***************************************************************************/
  724.  
  725.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  726.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  727.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  728.  
  729.  /***************************************************************************
  730.   * Add basic extensions to the system menu.                    *
  731.   ***************************************************************************/
  732.  
  733.   static MENUITEM MenuSeparator =
  734.     { MIT_END, MIS_SEPARATOR, 0, 0, NULL, 0 } ;
  735.  
  736.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  737.  
  738.   static MENUITEM MenuItems [] =
  739.   {
  740.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, NULL, 0 },
  741.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   NULL, 0 },
  742.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    NULL, 0 },
  743.     { MIT_END, MIS_TEXT,      0, IDM_CONFIGURE,        NULL, 0 },
  744.   } ;
  745.  
  746.   for ( int i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  747.   {
  748.     ResourceString MenuText ( Data->Library, i+IDS_SAVE_APPLICATION ) ;
  749.     AddSysMenuItem ( hwndFrame, MenuItems+i, MenuText.Ptr() ) ;
  750.   }
  751.  
  752.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  753.  
  754.  /***************************************************************************
  755.   * Add 'About' to the system menu.                        *
  756.   ***************************************************************************/
  757.  
  758.   static MENUITEM MenuAbout =
  759.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, NULL, 0 } ;
  760.  
  761.   ResourceString AboutText ( Data->Library, IDS_ABOUT ) ;
  762.  
  763.   AddSysMenuItem ( hwndFrame, &MenuAbout, AboutText.Ptr() ) ;
  764.  
  765.  /***************************************************************************
  766.   * Add 'Help' to the system menu.                        *
  767.   ***************************************************************************/
  768.  
  769.   static MENUITEM MenuHelp =
  770.     { MIT_END, MIS_HELP, 0, 0, NULL, 0 } ;
  771.  
  772.   ResourceString HelpText ( Data->Library, IDS_HELP ) ;
  773.  
  774.   AddSysMenuItem ( hwndFrame, &MenuHelp, HelpText.Ptr() ) ;
  775.  
  776.  /***************************************************************************
  777.   * Start the new load meter.                            *
  778.   ***************************************************************************/
  779.  
  780.   DosCreateThread ( &Data->IdleLoopTID, CounterThread, (ULONG)&Data->IdleCounter, 0, 4096 ) ;
  781.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->IdleLoopTID ) ;
  782.   DosSuspendThread ( Data->IdleLoopTID ) ;
  783.  
  784.   Data->Profile.IdleCount = 0 ;
  785.   Data->IdleCounter = 0 ;
  786.  
  787.   if ( Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  788.   {
  789.     DosResumeThread ( Data->IdleLoopTID ) ;
  790.   }
  791.  
  792.   PMONITOR_PARMS MonitorParms = PMONITOR_PARMS ( malloc ( sizeof(*MonitorParms) ) ) ;
  793.   MonitorParms->Counter = & Data->IdleCounter ;
  794.   MonitorParms->Interval = & Data->Profile.TimerInterval ;
  795.   MonitorParms->Owner = hwnd ;
  796.   DosCreateThread ( &Data->MonitorLoopTID, MonitorLoopThread, (ULONG)MonitorParms, 2, 8192 ) ;
  797.  
  798.  /***************************************************************************
  799.   * Add the program to the system task list.                    *
  800.   ***************************************************************************/
  801.  
  802.   ResourceString Title ( Data->Library, IDS_TITLE ) ;
  803.   Add2TaskList ( hwndFrame, Title.Ptr() ) ;
  804.  
  805.  /***************************************************************************
  806.   * Position & size the window.  For some reason, we must move and size     *
  807.   *   the window to the saved position before applying the resizing        *
  808.   *   function as fine-tuning.    Maybe the positioning request fails if        *
  809.   *   the window has no size?                            *
  810.   ***************************************************************************/
  811.  
  812.   WinSetWindowPos ( hwndFrame, HWND_BOTTOM,
  813.     Data->Profile.Position.x, Data->Profile.Position.y,
  814.     Data->Profile.Position.cx, Data->Profile.Position.cy,
  815.     SWP_SIZE | SWP_MOVE | SWP_ZORDER |
  816.     ( Data->Profile.Position.fl & SWP_MINIMIZE ) |
  817.     ( Data->Profile.Position.fl & SWP_RESTORE ) ) ;
  818.  
  819.   ResizeWindow ( hwnd, &Data->Profile ) ;
  820.  
  821.  /***************************************************************************
  822.   * Hide the controls if so configured.                     *
  823.   ***************************************************************************/
  824.  
  825.   if ( Data->Profile.HideControls
  826.     AND NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  827.   {
  828.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  829.  
  830.     HideControls
  831.     (
  832.       TRUE,
  833.       hwndFrame,
  834.       Data->hwndSysMenu,
  835.       Data->hwndTitleBar,
  836.       Data->hwndMinMax
  837.     ) ;
  838.   }
  839.  
  840.  /***************************************************************************
  841.   * Get the saved presentation parameters and reinstate them.            *
  842.   ***************************************************************************/
  843.  
  844.   if ( Data->Profile.fFontNameSize )
  845.   {
  846.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  847.       strlen((PCHAR)Data->Profile.FontNameSize)+1, Data->Profile.FontNameSize ) ;
  848.   }
  849.  
  850.   if ( Data->Profile.fBackColor )
  851.   {
  852.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  853.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  854.   }
  855.  
  856.   if ( Data->Profile.fTextColor )
  857.   {
  858.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  859.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  860.   }
  861.  
  862.  /***************************************************************************
  863.   * Determine our font size.                            *
  864.   ***************************************************************************/
  865.  
  866.   HPS hPS = WinGetPS ( hwnd ) ;
  867.   RECTL Rectangle ;
  868.   WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  869.   WinDrawText ( hPS, 1, (PSZ)" ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  870.   Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  871.   Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  872.   WinReleasePS ( hPS ) ;
  873.  
  874.  /***************************************************************************
  875.   * Now that the window's in order, make it visible.                        *
  876.   ***************************************************************************/
  877.  
  878.   WinShowWindow ( hwndFrame, TRUE ) ;
  879.  
  880.  /***************************************************************************
  881.   * Success?  Return no error.                            *
  882.   ***************************************************************************/
  883.  
  884.   return ( 0 ) ;
  885. }
  886.  
  887. /****************************************************************************
  888.  *                                        *
  889.  *    Destroy main window.                            *
  890.  *                                        *
  891.  ****************************************************************************/
  892.  
  893. STATIC MRESULT APIENTRY Destroy
  894. (
  895.   HWND hwnd,
  896.   USHORT msg,
  897.   MPARAM mp1,
  898.   MPARAM mp2
  899. )
  900. {
  901.  /***************************************************************************
  902.   * Find the instance data.                            *
  903.   ***************************************************************************/
  904.  
  905.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  906.  
  907.  /***************************************************************************
  908.   * Release the instance memory.                        *
  909.   ***************************************************************************/
  910.  
  911.   free ( Data ) ;
  912.  
  913.  /***************************************************************************
  914.   * We're done.                                                             *
  915.   ***************************************************************************/
  916.  
  917.   return ( MRFROMSHORT ( 0 ) ) ;
  918. }
  919.  
  920. /****************************************************************************
  921.  *                                        *
  922.  *    Process window resize message.                        *
  923.  *                                        *
  924.  ****************************************************************************/
  925.  
  926. STATIC MRESULT APIENTRY Size
  927. (
  928.   HWND hwnd,
  929.   USHORT msg,
  930.   MPARAM mp1,
  931.   MPARAM mp2
  932. )
  933. {
  934.  /***************************************************************************
  935.   * Find the instance data.                            *
  936.   ***************************************************************************/
  937.  
  938.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  939.  
  940.  /***************************************************************************
  941.   * Find out the window's new position and size.                            *
  942.   ***************************************************************************/
  943.  
  944.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  945.  
  946.   SWP Position ;
  947.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  948.  
  949.   if ( NOT ( Position.fl & SWP_MINIMIZE )
  950.     AND NOT ( Position.fl & SWP_MAXIMIZE ) )
  951.   {
  952.     Data->Profile.Position.x = Position.x ;
  953.     Data->Profile.Position.y = Position.y ;
  954.  
  955.     Data->Profile.Position.cx = Position.cx ;
  956.     Data->Profile.Position.cy = Position.cy ;
  957.   }
  958.  
  959.  /***************************************************************************
  960.   * If hiding the controls . . .                        *
  961.   ***************************************************************************/
  962.  
  963.   if ( Data->Profile.HideControls )
  964.   {
  965.  
  966.    /*************************************************************************
  967.     * If changing to or from minimized state . . .                *
  968.     *************************************************************************/
  969.  
  970.     if ( ( Position.fl & SWP_MINIMIZE ) != ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  971.     {
  972.  
  973.      /***********************************************************************
  974.       * Hide the controls if no longer minimized.                *
  975.       ***********************************************************************/
  976.  
  977.       HideControls
  978.       (
  979.     NOT ( Position.fl & SWP_MINIMIZE ),
  980.     hwndFrame,
  981.     Data->hwndSysMenu,
  982.     Data->hwndTitleBar,
  983.     Data->hwndMinMax
  984.       ) ;
  985.     }
  986.   }
  987.  
  988.   Data->Profile.Position.fl = Position.fl ;
  989.  
  990.  /***************************************************************************
  991.   * We're done.                                                             *
  992.   ***************************************************************************/
  993.  
  994.   return ( 0 ) ;
  995. }
  996.  
  997. /****************************************************************************
  998.  *                                        *
  999.  *    Process SAVE APPLICATION message.                    *
  1000.  *                                        *
  1001.  ****************************************************************************/
  1002.  
  1003. STATIC MRESULT APIENTRY SaveApplication
  1004. (
  1005.   HWND hwnd,
  1006.   USHORT msg,
  1007.   MPARAM mp1,
  1008.   MPARAM mp2
  1009. )
  1010. {
  1011.  /***************************************************************************
  1012.   * Find the instance data.                            *
  1013.   ***************************************************************************/
  1014.  
  1015.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1016.  
  1017.  /***************************************************************************
  1018.   * Call function to put all profile data out to the system.            *
  1019.   ***************************************************************************/
  1020.  
  1021.   PutProfile ( Data->ProfileHandle, &Data->Profile ) ;
  1022.  
  1023.  /***************************************************************************
  1024.   * We're done.  Let the system complete default processing.                *
  1025.   ***************************************************************************/
  1026.  
  1027.   return ( WinDefWindowProc ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ) ;
  1028. }
  1029.  
  1030. /****************************************************************************
  1031.  *                                        *
  1032.  *    Repaint entire window.                            *
  1033.  *                                        *
  1034.  ****************************************************************************/
  1035.  
  1036. STATIC MRESULT APIENTRY Paint
  1037. (
  1038.   HWND hwnd,
  1039.   USHORT msg,
  1040.   MPARAM mp1,
  1041.   MPARAM mp2
  1042. )
  1043. {
  1044.  /***************************************************************************
  1045.   * Find the instance data.                            *
  1046.   ***************************************************************************/
  1047.  
  1048.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1049.  
  1050.  /***************************************************************************
  1051.   * Get presentation space and make it use RGB colors.                *
  1052.   ***************************************************************************/
  1053.  
  1054.   HPS hPS = WinBeginPaint ( hwnd, NULL, NULL ) ;
  1055.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  1056.  
  1057.  /***************************************************************************
  1058.   * Clear the window.                                *
  1059.   ***************************************************************************/
  1060.  
  1061.   RECTL Rectangle ;
  1062.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  1063.  
  1064.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  1065.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  1066.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  1067.  
  1068.  /***************************************************************************
  1069.   * Release presentation space.                         *
  1070.   ***************************************************************************/
  1071.  
  1072.   WinEndPaint ( hPS ) ;
  1073.  
  1074.  /***************************************************************************
  1075.   * Update the window and return.                        *
  1076.   ***************************************************************************/
  1077.  
  1078.   UpdateWindow ( hwnd, Data, TRUE ) ;
  1079.  
  1080.   return ( 0 ) ;
  1081. }
  1082.  
  1083. /****************************************************************************
  1084.  *                                        *
  1085.  *    Process commands received by Main Window                *
  1086.  *                                        *
  1087.  ****************************************************************************/
  1088.  
  1089. STATIC MRESULT APIENTRY Command
  1090. (
  1091.   HWND hwnd,
  1092.   USHORT msg,
  1093.   MPARAM mp1,
  1094.   MPARAM mp2
  1095. )
  1096. {
  1097.  /***************************************************************************
  1098.   * Dispatch all other commands through the method table.            *
  1099.   ***************************************************************************/
  1100.  
  1101.   static METHOD Methods [] =
  1102.   {
  1103.     { IDM_SAVE_APPLICATION, SaveApplication },
  1104.     { IDM_RESET_DEFAULTS,   ResetDefaults   },
  1105.     { IDM_HIDE_CONTROLS,    HideControlsCmd },
  1106.     { IDM_CONFIGURE,        Configure        },
  1107.     { IDM_EXIT,         Exit        },
  1108.     { IDM_ABOUT,        About        },
  1109.   } ;
  1110.  
  1111.   return ( DispatchMessage ( hwnd, SHORT1FROMMP(mp1), mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), NULL ) ) ;
  1112. }
  1113.  
  1114. /****************************************************************************
  1115.  *                                        *
  1116.  *    Process Reset Defaults menu command.                    *
  1117.  *                                        *
  1118.  ****************************************************************************/
  1119.  
  1120. STATIC MRESULT APIENTRY ResetDefaults
  1121.   HWND hwnd, 
  1122.   USHORT msg, 
  1123.   MPARAM mp1, 
  1124.   MPARAM mp2
  1125. )
  1126. {
  1127.  /***************************************************************************
  1128.   * Find the instance data.                            *
  1129.   ***************************************************************************/
  1130.  
  1131.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1132.  
  1133.  /***************************************************************************
  1134.   * Reset all profile data for this program.                    *
  1135.   ***************************************************************************/
  1136.  
  1137.   PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, NULL, NULL, 0 ) ;
  1138.  
  1139.  /***************************************************************************
  1140.   * Reset the program's presentation parameters.                            *
  1141.   ***************************************************************************/
  1142.  
  1143.   WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  1144.   WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  1145.   WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  1146.  
  1147.  /***************************************************************************
  1148.   * Done.                                    *
  1149.   ***************************************************************************/
  1150.  
  1151.   return ( MRFROMSHORT ( 0 ) ) ;
  1152. }
  1153.  
  1154. /****************************************************************************
  1155.  *                                        *
  1156.  *    Process Hide Controls menu command.                    *
  1157.  *                                        *
  1158.  ****************************************************************************/
  1159.  
  1160. STATIC MRESULT APIENTRY HideControlsCmd
  1161.   HWND hwnd, 
  1162.   USHORT msg, 
  1163.   MPARAM mp1, 
  1164.   MPARAM mp2
  1165. )
  1166. {
  1167.  /***************************************************************************
  1168.   * Find the instance data.                            *
  1169.   ***************************************************************************/
  1170.  
  1171.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1172.  
  1173.  /***************************************************************************
  1174.   * Toggle the Hide Controls setting.                        *
  1175.   ***************************************************************************/
  1176.  
  1177.   Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  1178.   Data->Profile.fHideControls = TRUE ;
  1179.  
  1180.  /***************************************************************************
  1181.   * Get the frame handle.                                *
  1182.   ***************************************************************************/
  1183.  
  1184.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1185.  
  1186.  /***************************************************************************
  1187.   * If controls aren't hidden yet, update the menu check-mark.              *
  1188.   ***************************************************************************/
  1189.  
  1190.   if ( Data->Profile.HideControls )
  1191.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1192.  
  1193.  /***************************************************************************
  1194.   * If not minimized right now, hide or reveal the controls.            *
  1195.   ***************************************************************************/
  1196.  
  1197.   if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1198.   {
  1199.     HideControls
  1200.     (
  1201.       Data->Profile.HideControls,
  1202.       hwndFrame,
  1203.       Data->hwndSysMenu,
  1204.       Data->hwndTitleBar,
  1205.       Data->hwndMinMax
  1206.     ) ;
  1207.   }
  1208.  
  1209.  /***************************************************************************
  1210.   * If controls are no longer hidden, update the menu check-mark.        *
  1211.   ***************************************************************************/
  1212.  
  1213.   if ( NOT Data->Profile.HideControls )
  1214.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1215.  
  1216.  /***************************************************************************
  1217.   * Done.                                    *
  1218.   ***************************************************************************/
  1219.  
  1220.   return ( MRFROMSHORT ( 0 ) ) ;
  1221. }
  1222.  
  1223. /****************************************************************************
  1224.  *                                        *
  1225.  *    Process Configure command.                        *
  1226.  *                                        *
  1227.  ****************************************************************************/
  1228.  
  1229. STATIC MRESULT APIENTRY Configure
  1230.   HWND hwnd, 
  1231.   USHORT msg, 
  1232.   MPARAM mp1, 
  1233.   MPARAM mp2
  1234. )
  1235. {
  1236.  /***************************************************************************
  1237.   * Find the instance data.                            *
  1238.   ***************************************************************************/
  1239.  
  1240.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1241.  
  1242.  /***************************************************************************
  1243.   * Invoke the Configure dialog.  If cancelled, just return.            *
  1244.   ***************************************************************************/
  1245.  
  1246.   CONFIG_PARMS Parms ;
  1247.   Parms.id          = IDD_CONFIGURE ;
  1248.   Parms.hwndHelp      = WinQueryHelpInstance ( hwnd ) ;
  1249.   Parms.HideControls  = Data->Profile.HideControls ;
  1250.   Parms.Float          = Data->Profile.Float ;
  1251.   Parms.TimerInterval = Data->Profile.TimerInterval ;
  1252.  
  1253.   Parms.ItemCount     = Data->Profile.ItemCount ;
  1254.  
  1255.   PSZ  ItemNames [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1256.   BOOL ItemFlags [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  1257.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  1258.   {
  1259.     ItemNames[i] = Data->Profile.Items[i]->QueryOption () ;
  1260.     ItemFlags[i] = Data->Profile.Items[i]->QueryFlag () ;
  1261.   }
  1262.   Parms.ItemNames = ItemNames ;
  1263.   Parms.ItemFlags = ItemFlags ;
  1264.  
  1265.   if ( WinDlgBox ( HWND_DESKTOP, hwnd, PFNWP(ConfigureProcessor),
  1266.     Data->Library, IDD_CONFIGURE, &Parms ) == FALSE )
  1267.   {
  1268.     return ( MRFROMSHORT ( 0 ) ) ;
  1269.   }
  1270.  
  1271.  /***************************************************************************
  1272.   * Save the new timer interval.                        *
  1273.   ***************************************************************************/
  1274.  
  1275.   Data->Profile.fTimerInterval = TRUE ;
  1276.   Data->Profile.TimerInterval = Parms.TimerInterval ;
  1277.  
  1278.  /***************************************************************************
  1279.   * Save the float-to-top flag.                         *
  1280.   ***************************************************************************/
  1281.  
  1282.   Data->Profile.fFloat = TRUE ;
  1283.   Data->Profile.Float = Parms.Float ;
  1284.  
  1285.  /***************************************************************************
  1286.   * Save the hide controls flag, and adjust the window if it changed.        *
  1287.   ***************************************************************************/
  1288.  
  1289.   Data->Profile.fHideControls = TRUE ;
  1290.   if ( Data->Profile.HideControls != Parms.HideControls )
  1291.   {
  1292.     HWND FrameWindow = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1293.     Data->Profile.HideControls = Parms.HideControls ;
  1294.     if ( Data->Profile.HideControls )
  1295.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1296.     if ( NOT ( Data->Profile.Position.fl & SWP_MINIMIZE ) )
  1297.     {
  1298.       HideControls
  1299.       (
  1300.     Data->Profile.HideControls,
  1301.     FrameWindow,
  1302.     Data->hwndSysMenu,
  1303.     Data->hwndTitleBar,
  1304.     Data->hwndMinMax
  1305.       ) ;
  1306.     }
  1307.     if ( NOT Data->Profile.HideControls )
  1308.       CheckMenuItem ( FrameWindow, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1309.   }
  1310.  
  1311.  /***************************************************************************
  1312.   * Determine if the display item list has changed.  If not, return.        *
  1313.   ***************************************************************************/
  1314.  
  1315.   BOOL ItemsChanged = FALSE ;
  1316.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1317.   {
  1318.     if ( ItemFlags[i] != Data->Profile.Items[i]->QueryFlag() )
  1319.     {
  1320.       ItemsChanged = TRUE ;
  1321.       break ;
  1322.     }
  1323.   }
  1324.  
  1325.   if ( NOT ItemsChanged )
  1326.   {
  1327.     return ( MRFROMSHORT ( 0 ) ) ;
  1328.   }
  1329.  
  1330.  /***************************************************************************
  1331.   * If CPU load monitoring has changed, start/stop the monitoring thread.   *
  1332.   ***************************************************************************/
  1333.  
  1334.   if ( ItemFlags[ITEM_CPULOAD] != Data->Profile.Items[ITEM_CPULOAD]->QueryFlag() )
  1335.   {
  1336.     if ( ItemFlags[ITEM_CPULOAD] )
  1337.       DosResumeThread ( Data->IdleLoopTID ) ;
  1338.     else
  1339.       DosSuspendThread ( Data->IdleLoopTID ) ;
  1340.   }
  1341.  
  1342.  /***************************************************************************
  1343.   * Save the new item flags.                            *
  1344.   ***************************************************************************/
  1345.  
  1346.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1347.   {
  1348.     if ( ItemFlags[i] )
  1349.       Data->Profile.Items[i]->SetFlag ( ) ;
  1350.     else
  1351.       Data->Profile.Items[i]->ResetFlag ( ) ;
  1352.   }
  1353.  
  1354.  /***************************************************************************
  1355.   * Resize the display window.                            *
  1356.   ***************************************************************************/
  1357.  
  1358.   ResizeWindow ( hwnd, &Data->Profile ) ;
  1359.  
  1360.  /***************************************************************************
  1361.   * Done.                                    *
  1362.   ***************************************************************************/
  1363.  
  1364.   return ( MRFROMSHORT ( 0 ) ) ;
  1365. }
  1366.  
  1367. /****************************************************************************
  1368.  *                                        *
  1369.  *    Process About menu command.                        *
  1370.  *                                        *
  1371.  ****************************************************************************/
  1372.  
  1373. STATIC MRESULT APIENTRY About
  1374.   HWND hwnd, 
  1375.   USHORT msg, 
  1376.   MPARAM mp1, 
  1377.   MPARAM mp2
  1378. )
  1379. {
  1380.  /***************************************************************************
  1381.   * Find the instance data.                            *
  1382.   ***************************************************************************/
  1383.  
  1384.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1385.  
  1386.  /***************************************************************************
  1387.   * Invoke the About dialog.                            *
  1388.   ***************************************************************************/
  1389.  
  1390.   ABOUT_PARMS Parms ;
  1391.   Parms.id = IDD_ABOUT ;
  1392.   Parms.hwndHelp = WinQueryHelpInstance ( hwnd ) ;
  1393.  
  1394.   WinDlgBox ( HWND_DESKTOP, hwnd, PFNWP(AboutProcessor),
  1395.     Data->Library, IDD_ABOUT, &Parms ) ;
  1396.  
  1397.  /***************************************************************************
  1398.   * Done.                                    *
  1399.   ***************************************************************************/
  1400.  
  1401.   return ( MRFROMSHORT ( 0 ) ) ;
  1402. }
  1403.  
  1404. /****************************************************************************
  1405.  *                                        *
  1406.  *    Process Mouse Button being pressed.                    *
  1407.  *                                        *
  1408.  ****************************************************************************/
  1409.  
  1410. STATIC MRESULT APIENTRY ButtonDown
  1411. (
  1412.   HWND hwnd,
  1413.   USHORT msg,
  1414.   MPARAM mp1,
  1415.   MPARAM mp2
  1416. )
  1417. {
  1418.  /***************************************************************************
  1419.   * Find the instance data.                            *
  1420.   ***************************************************************************/
  1421.  
  1422.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1423.  
  1424.  /***************************************************************************
  1425.   * Determine the new window position.                        *
  1426.   ***************************************************************************/
  1427.  
  1428.   TRACKINFO TrackInfo ;
  1429.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  1430.  
  1431.   TrackInfo.cxBorder = 1 ;
  1432.   TrackInfo.cyBorder = 1 ;
  1433.   TrackInfo.cxGrid = 1 ;
  1434.   TrackInfo.cyGrid = 1 ;
  1435.   TrackInfo.cxKeyboard = 8 ;
  1436.   TrackInfo.cyKeyboard = 8 ;
  1437.  
  1438.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  1439.  
  1440.   SWP Position ;
  1441.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1442.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1443.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1444.   TrackInfo.rclTrack.yBottom = Position.y ;
  1445.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1446.  
  1447.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1448.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1449.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1450.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1451.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1452.  
  1453.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1454.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1455.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1456.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1457.  
  1458.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1459.  
  1460.   if ( WinTrackRect ( HWND_DESKTOP, NULL, &TrackInfo ) )
  1461.   {
  1462.     WinSetWindowPos ( hwndFrame, NULL,
  1463.       (SHORT) TrackInfo.rclTrack.xLeft,
  1464.       (SHORT) TrackInfo.rclTrack.yBottom,
  1465.       0, 0, SWP_MOVE ) ;
  1466.   }
  1467.  
  1468.  /***************************************************************************
  1469.   * Return through the default processor, letting window activation        *
  1470.   *   and other system functions occur.                     *
  1471.   ***************************************************************************/
  1472.  
  1473.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1474. }
  1475.  
  1476. /****************************************************************************
  1477.  *                                        *
  1478.  *    Process Mouse Button having been double-clicked.            *
  1479.  *                                        *
  1480.  ****************************************************************************/
  1481.  
  1482. STATIC MRESULT APIENTRY ButtonDblClick
  1483. (
  1484.   HWND hwnd,
  1485.   USHORT msg,
  1486.   MPARAM mp1,
  1487.   MPARAM mp2
  1488. )
  1489. {
  1490.  /***************************************************************************
  1491.   * Send message to self to stop hiding the controls.                *
  1492.   ***************************************************************************/
  1493.  
  1494.   WinPostMsg ( hwnd, WM_COMMAND,
  1495.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1496.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1497.  
  1498.  /***************************************************************************
  1499.   * Return through the default processor, letting window activation        *
  1500.   *   and other system functions occur.                     *
  1501.   ***************************************************************************/
  1502.  
  1503.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1504. }
  1505.  
  1506. /****************************************************************************
  1507.  *                                        *
  1508.  *    Process Presentation Parameter Changed notification.            *
  1509.  *                                        *
  1510.  ****************************************************************************/
  1511.  
  1512. STATIC MRESULT APIENTRY PresParamChanged
  1513. (
  1514.   HWND hwnd,
  1515.   USHORT msg,
  1516.   MPARAM mp1,
  1517.   MPARAM mp2
  1518. )
  1519. {
  1520.  /***************************************************************************
  1521.   * Find the instance data.                            *
  1522.   ***************************************************************************/
  1523.  
  1524.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1525.  
  1526.  /***************************************************************************
  1527.   * Get the presentation parameter that changed.                *
  1528.   ***************************************************************************/
  1529.  
  1530.   switch ( LONGFROMMP(mp1) )
  1531.   {
  1532.  
  1533.    /*************************************************************************
  1534.     * If font, note the fact that we now have a font to be saved as        *
  1535.     *    part of the configuration.  Get the font metrics and resize        *
  1536.     *    the window appropriately.                        *
  1537.     *************************************************************************/
  1538.  
  1539.     case PP_FONTNAMESIZE:
  1540.     {
  1541.       ULONG ppid ;
  1542.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1543.     sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1544.     0 ) )
  1545.       {
  1546.     Data->Profile.fFontNameSize = TRUE ;
  1547.       }
  1548.       else
  1549.       {
  1550.     strcpy ( (PCHAR)Data->Profile.FontNameSize, "" ) ;
  1551.     Data->Profile.fFontNameSize = FALSE ;
  1552.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", NULL, 0 ) ;
  1553.       }
  1554.  
  1555.       HPS hPS = WinGetPS ( hwnd ) ;
  1556.       RECTL Rectangle ;
  1557.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1558.       WinDrawText ( hPS, 1, (PSZ)" ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1559.       Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  1560.       Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  1561.       WinReleasePS ( hPS ) ;
  1562.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1563.       break ;
  1564.     }
  1565.  
  1566.    /*************************************************************************
  1567.     * If background color, note the fact and repaint the window.        *
  1568.     *************************************************************************/
  1569.  
  1570.     case PP_BACKGROUNDCOLOR:
  1571.     {
  1572.       ULONG ppid ;
  1573.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1574.     sizeof(Data->Profile.BackColor), &Data->Profile.BackColor, 0 ) )
  1575.       {
  1576.     Data->Profile.fBackColor = TRUE ;
  1577.       }
  1578.       else
  1579.       {
  1580.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1581.     Data->Profile.fBackColor = FALSE ;
  1582.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", NULL, 0 ) ;
  1583.       }
  1584.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1585.       break ;
  1586.     }
  1587.  
  1588.    /*************************************************************************
  1589.     * If foreground color, note the fact and repaint the window.        *
  1590.     *************************************************************************/
  1591.  
  1592.     case PP_FOREGROUNDCOLOR:
  1593.     {
  1594.       ULONG ppid ;
  1595.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1596.     sizeof(Data->Profile.TextColor), &Data->Profile.TextColor, 0 ) )
  1597.       {
  1598.     Data->Profile.fTextColor = TRUE ;
  1599.       }
  1600.       else
  1601.       {
  1602.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1603.     Data->Profile.fTextColor = FALSE ;
  1604.     PrfWriteProfileData ( Data->ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", NULL, 0 ) ;
  1605.       }
  1606.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1607.       break ;
  1608.     }
  1609.   }
  1610.  
  1611.  /***************************************************************************
  1612.   * Return through the default processor, letting window activation        *
  1613.   *   and other system functions occur.                     *
  1614.   ***************************************************************************/
  1615.  
  1616.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1617. }
  1618.  
  1619. /****************************************************************************
  1620.  *                                        *
  1621.  *    Process System Color Change notification.                *
  1622.  *                                        *
  1623.  ****************************************************************************/
  1624.  
  1625. STATIC MRESULT APIENTRY SysColorChange
  1626. (
  1627.   HWND hwnd,
  1628.   USHORT msg,
  1629.   MPARAM mp1,
  1630.   MPARAM mp2
  1631. )
  1632. {
  1633.  /***************************************************************************
  1634.   * Find the instance data.                            *
  1635.   ***************************************************************************/
  1636.  
  1637.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1638.  
  1639.  /***************************************************************************
  1640.   * If we aren't using custom colors, then query for the new defaults.      *
  1641.   ***************************************************************************/
  1642.  
  1643.   if ( NOT Data->Profile.fBackColor )
  1644.   {
  1645.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1646.   }
  1647.  
  1648.   if ( NOT Data->Profile.fTextColor )
  1649.   {
  1650.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1651.   }
  1652.  
  1653.  /***************************************************************************
  1654.   * Return value must be NULL, according to the documentation.            *
  1655.   ***************************************************************************/
  1656.  
  1657.   return ( MRFROMP ( NULL ) ) ;
  1658. }
  1659.  
  1660. /****************************************************************************
  1661.  *                                        *
  1662.  *    Process Query for Keys Help resource id.                *
  1663.  *                                        *
  1664.  ****************************************************************************/
  1665.  
  1666. STATIC MRESULT APIENTRY QueryKeysHelp
  1667. (
  1668.   HWND hwnd,
  1669.   USHORT msg,
  1670.   MPARAM mp1,
  1671.   MPARAM mp2
  1672. )
  1673. {
  1674.  /***************************************************************************
  1675.   * Simply return the ID of the Keys Help panel.                *
  1676.   ***************************************************************************/
  1677.  
  1678.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1679. }
  1680.  
  1681. /****************************************************************************
  1682.  *                                        *
  1683.  *    Process Help Manager Error                        *
  1684.  *                                        *
  1685.  ****************************************************************************/
  1686.  
  1687. STATIC MRESULT APIENTRY HelpError
  1688.   HWND hwnd, 
  1689.   USHORT msg, 
  1690.   MPARAM mp1, 
  1691.   MPARAM mp2
  1692. )
  1693. {
  1694.  /***************************************************************************
  1695.   * Local Declarations                                *
  1696.   ***************************************************************************/
  1697.  
  1698.   static struct
  1699.   {
  1700.     ULONG Error ;
  1701.     USHORT StringId ;
  1702.   }
  1703.   HelpErrors [] =
  1704.   {
  1705.     { HMERR_NO_FRAME_WND_IN_CHAIN,     IDS_HMERR_NO_FRAME_WND_IN_CHAIN },
  1706.     { HMERR_INVALID_ASSOC_APP_WND,     IDS_HMERR_INVALID_ASSOC_APP_WND },
  1707.     { HMERR_INVALID_ASSOC_HELP_INST,   IDS_HMERR_INVALID_ASSOC_HELP_IN },
  1708.     { HMERR_INVALID_DESTROY_HELP_INST, IDS_HMERR_INVALID_DESTROY_HELP_ },
  1709.     { HMERR_NO_HELP_INST_IN_CHAIN,     IDS_HMERR_NO_HELP_INST_IN_CHAIN },
  1710.     { HMERR_INVALID_HELP_INSTANCE_HDL, IDS_HMERR_INVALID_HELP_INSTANCE },
  1711.     { HMERR_INVALID_QUERY_APP_WND,     IDS_HMERR_INVALID_QUERY_APP_WND },
  1712.     { HMERR_HELP_INST_CALLED_INVALID,  IDS_HMERR_HELP_INST_CALLED_INVA },
  1713.     { HMERR_HELPTABLE_UNDEFINE,        IDS_HMERR_HELPTABLE_UNDEFINE    },
  1714.     { HMERR_HELP_INSTANCE_UNDEFINE,    IDS_HMERR_HELP_INSTANCE_UNDEFIN },
  1715.     { HMERR_HELPITEM_NOT_FOUND,        IDS_HMERR_HELPITEM_NOT_FOUND    },
  1716.     { HMERR_INVALID_HELPSUBITEM_SIZE,  IDS_HMERR_INVALID_HELPSUBITEM_S },
  1717.     { HMERR_HELPSUBITEM_NOT_FOUND,     IDS_HMERR_HELPSUBITEM_NOT_FOUND },
  1718.     { HMERR_INDEX_NOT_FOUND,           IDS_HMERR_INDEX_NOT_FOUND       },
  1719.     { HMERR_CONTENT_NOT_FOUND,           IDS_HMERR_CONTENT_NOT_FOUND     },
  1720.     { HMERR_OPEN_LIB_FILE,           IDS_HMERR_OPEN_LIB_FILE           },
  1721.     { HMERR_READ_LIB_FILE,           IDS_HMERR_READ_LIB_FILE           },
  1722.     { HMERR_CLOSE_LIB_FILE,           IDS_HMERR_CLOSE_LIB_FILE        },
  1723.     { HMERR_INVALID_LIB_FILE,           IDS_HMERR_INVALID_LIB_FILE      },
  1724.     { HMERR_NO_MEMORY,               IDS_HMERR_NO_MEMORY           },
  1725.     { HMERR_ALLOCATE_SEGMENT,           IDS_HMERR_ALLOCATE_SEGMENT      },
  1726.     { HMERR_FREE_MEMORY,           IDS_HMERR_FREE_MEMORY           },
  1727.     { HMERR_PANEL_NOT_FOUND,           IDS_HMERR_PANEL_NOT_FOUND       },
  1728.     { HMERR_DATABASE_NOT_OPEN,           IDS_HMERR_DATABASE_NOT_OPEN     },
  1729.     { 0,                   IDS_HMERR_UNKNOWN           }
  1730.   } ;
  1731.  
  1732.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1733.  
  1734.  /***************************************************************************
  1735.   * Find the instance data.                            *
  1736.   ***************************************************************************/
  1737.  
  1738.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1739.  
  1740.  /***************************************************************************
  1741.   * Find the error code in the message table.                    *
  1742.   ***************************************************************************/
  1743.  
  1744.   int Index = 0 ;
  1745.   while ( HelpErrors[Index].Error
  1746.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1747.   {
  1748.     Index ++ ;
  1749.   }
  1750.  
  1751.  /***************************************************************************
  1752.   * Get the message texts.                            *
  1753.   ***************************************************************************/
  1754.  
  1755.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1756.  
  1757.   ResourceString Message ( Data->Library, HelpErrors[Index].StringId ) ;
  1758.  
  1759.  /***************************************************************************
  1760.   * Display the error message.                            *
  1761.   ***************************************************************************/
  1762.  
  1763.   WinMessageBox
  1764.   (
  1765.     HWND_DESKTOP,
  1766.     hwnd,
  1767.     Message.Ptr(),
  1768.     Title.Ptr(),
  1769.     0,
  1770.     MB_OK | MB_WARNING
  1771.   ) ;
  1772.  
  1773.  /***************************************************************************
  1774.   * Return zero, indicating that the message was processed.            *
  1775.   ***************************************************************************/
  1776.  
  1777.   return ( MRFROMSHORT ( 0 ) ) ;
  1778. }
  1779.  
  1780. /****************************************************************************
  1781.  *                                        *
  1782.  *    Process "Extended Help Undefined" notification                *
  1783.  *                                        *
  1784.  ****************************************************************************/
  1785.  
  1786. STATIC MRESULT APIENTRY ExtHelpUndefined
  1787.   HWND hwnd, 
  1788.   USHORT msg, 
  1789.   MPARAM mp1, 
  1790.   MPARAM mp2
  1791. )
  1792. {
  1793.  /***************************************************************************
  1794.   * Find the instance data.                            *
  1795.   ***************************************************************************/
  1796.  
  1797.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1798.  
  1799.  /***************************************************************************
  1800.   * Get the message texts.                            *
  1801.   ***************************************************************************/
  1802.  
  1803.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1804.  
  1805.   ResourceString Message ( Data->Library, IDS_HMERR_EXTHELPUNDEFINED ) ;
  1806.  
  1807.  /***************************************************************************
  1808.   * Display the error message.                            *
  1809.   ***************************************************************************/
  1810.  
  1811.   WinMessageBox
  1812.   (
  1813.     HWND_DESKTOP,
  1814.     hwnd,
  1815.     Message.Ptr(),
  1816.     Title.Ptr(),
  1817.     0,
  1818.     MB_OK | MB_WARNING
  1819.   ) ;
  1820.  
  1821.  /***************************************************************************
  1822.   * Return zero, indicating that the message was processed.            *
  1823.   ***************************************************************************/
  1824.  
  1825.   return ( MRFROMSHORT ( 0 ) ) ;
  1826. }
  1827.  
  1828. /****************************************************************************
  1829.  *                                        *
  1830.  *    Process "Help Subitem Not Found" notification                *
  1831.  *                                        *
  1832.  ****************************************************************************/
  1833.  
  1834. STATIC MRESULT APIENTRY HelpSubitemNotFound
  1835.   HWND hwnd, 
  1836.   USHORT msg, 
  1837.   MPARAM mp1, 
  1838.   MPARAM mp2
  1839. )
  1840. {
  1841.  /***************************************************************************
  1842.   * Find the instance data.                            *
  1843.   ***************************************************************************/
  1844.  
  1845.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1846.  
  1847.  /***************************************************************************
  1848.   * Get the title text.                             *
  1849.   ***************************************************************************/
  1850.  
  1851.   ResourceString Title ( Data->Library, IDS_HMERR ) ;
  1852.  
  1853.  /***************************************************************************
  1854.   * Format the error message.                            *
  1855.   ***************************************************************************/
  1856.  
  1857.   USHORT Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  1858.   USHORT Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  1859.  
  1860.   ResourceString Frame     ( Data->Library, IDS_HELPMODE_FRAME ) ;
  1861.   ResourceString Menu     ( Data->Library, IDS_HELPMODE_MENU ) ;
  1862.   ResourceString Window  ( Data->Library, IDS_HELPMODE_WINDOW ) ;
  1863.   ResourceString Unknown ( Data->Library, IDS_HELPMODE_UNKNOWN ) ;
  1864.  
  1865.   PBYTE Mode ;
  1866.   switch ( SHORT1FROMMP ( mp1 ) )
  1867.   {
  1868.     case HLPM_FRAME:
  1869.       Mode = Frame.Ptr() ;
  1870.       break ;
  1871.  
  1872.     case HLPM_MENU:
  1873.       Mode = Menu.Ptr() ;
  1874.       break ;
  1875.  
  1876.     case HLPM_WINDOW:
  1877.       Mode = Window.Ptr() ;
  1878.       break ;
  1879.  
  1880.     default:
  1881.       Mode = Unknown.Ptr() ;
  1882.   }
  1883.  
  1884.   ResourceString Format ( Data->Library, IDS_HELPSUBITEMNOTFOUND ) ;
  1885.  
  1886.   BYTE Message [200] ;
  1887.   sprintf ( (PCHAR)Message, PCHAR(Format.Ptr()), Mode, Topic, Subtopic ) ;
  1888.  
  1889.  /***************************************************************************
  1890.   * Display the error message.                            *
  1891.   ***************************************************************************/
  1892.  
  1893.   WinMessageBox
  1894.   (
  1895.     HWND_DESKTOP,
  1896.     hwnd,
  1897.     Message,
  1898.     Title.Ptr(),
  1899.     0,
  1900.     MB_OK | MB_WARNING
  1901.   ) ;
  1902.  
  1903.  /***************************************************************************
  1904.   * Return zero, indicating that the message was processed.            *
  1905.   ***************************************************************************/
  1906.  
  1907.   return ( MRFROMSHORT ( 0 ) ) ;
  1908. }
  1909.  
  1910. /****************************************************************************
  1911.  *                                        *
  1912.  *    Process Refresh message.                        *
  1913.  *                                        *
  1914.  ****************************************************************************/
  1915.  
  1916. STATIC MRESULT APIENTRY Refresh
  1917.   HWND hwnd, 
  1918.   USHORT msg, 
  1919.   MPARAM mp1, 
  1920.   MPARAM mp2
  1921. )
  1922. {
  1923.  /***************************************************************************
  1924.   * Find the instance data.                            *
  1925.   ***************************************************************************/
  1926.  
  1927.   PDATA Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1928.  
  1929.  /***************************************************************************
  1930.   * If we're supposed to float the window, do so here.                      *
  1931.   ***************************************************************************/
  1932.  
  1933.   if ( Data->Profile.Float )
  1934.     WinSetWindowPos ( WinQueryWindow(hwnd,QW_PARENT), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ) ;
  1935.  
  1936.  /***************************************************************************
  1937.   * Save the idle counter.                            *
  1938.   ***************************************************************************/
  1939.  
  1940.   Data->Profile.IdleCount = LONGFROMMP ( mp1 ) ;
  1941.  
  1942.  /***************************************************************************
  1943.   * Determine if drive mask has changed.                    *
  1944.   ***************************************************************************/
  1945.  
  1946.   ULONG Drive ;
  1947.   ULONG Drives ;
  1948.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  1949.  
  1950.   if ( Drives != Data->Drives )
  1951.   {
  1952.    /*************************************************************************
  1953.     * It has.  First save the display options.                    *
  1954.     *************************************************************************/
  1955.  
  1956.     SaveApplication ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ;
  1957.  
  1958.    /*************************************************************************
  1959.     * Next, update the drive item list.                     *
  1960.     *************************************************************************/
  1961.  
  1962.     UpdateDriveList ( Data->Anchor, Data->Library, Data->ProfileHandle, 
  1963.       &Data->Profile, Data->Drives, Drives ) ;
  1964.  
  1965.    /*************************************************************************
  1966.     * If the controls are hidden, hide the whole window and reveal the        *
  1967.     *    controls.  Otherwise the menu wouldn't get updated correctly.       *
  1968.     *************************************************************************/
  1969.  
  1970.     if ( Data->Profile.HideControls )
  1971.     {
  1972.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), FALSE ) ;
  1973.       HideControls
  1974.       (
  1975.     FALSE,
  1976.     WinQueryWindow ( hwnd, QW_PARENT ),
  1977.     Data->hwndSysMenu,
  1978.     Data->hwndTitleBar,
  1979.     Data->hwndMinMax
  1980.       ) ;
  1981.     }
  1982.  
  1983.    /*************************************************************************
  1984.     * If the controls were supposed to be hidden, hide them once more and   *
  1985.     *    show the window to the world again.                    *
  1986.     *************************************************************************/
  1987.  
  1988.     if ( Data->Profile.HideControls )
  1989.     {
  1990.       HideControls
  1991.       (
  1992.     TRUE,
  1993.     WinQueryWindow ( hwnd, QW_PARENT ),
  1994.     Data->hwndSysMenu,
  1995.     Data->hwndTitleBar,
  1996.     Data->hwndMinMax
  1997.       ) ;
  1998.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT), TRUE ) ;
  1999.     }
  2000.  
  2001.    /*************************************************************************
  2002.     * Save the updated drive mask.                        *
  2003.     *************************************************************************/
  2004.  
  2005.     Data->Drives = Drives ;
  2006.  
  2007.    /*************************************************************************
  2008.     * Resize the window to accommodate the new option list.            *
  2009.     *************************************************************************/
  2010.  
  2011.     ResizeWindow ( hwnd, &Data->Profile ) ;
  2012.   }
  2013.  
  2014.  /***************************************************************************
  2015.   * Update the statistics.                            *
  2016.   ***************************************************************************/
  2017.  
  2018.   UpdateWindow ( hwnd, Data, FALSE ) ;
  2019.  
  2020.  /***************************************************************************
  2021.   * Return zero, indicating that the message was processed.            *
  2022.   ***************************************************************************/
  2023.  
  2024.   return ( MRFROMSHORT ( 0 ) ) ;
  2025. }
  2026.  
  2027.  
  2028. /****************************************************************************
  2029.  *                                        *
  2030.  *                 Get Profile Data                    *
  2031.  *                                        *
  2032.  ****************************************************************************/
  2033.  
  2034. STATIC int GetProfile ( HAB Anchor, HMODULE Library, HINI ProfileHandle, PPROFILE Profile )
  2035. {
  2036.  /***************************************************************************
  2037.   * Get the window's current size and position.                             *
  2038.   ***************************************************************************/
  2039.  
  2040.   #pragma pack(2)
  2041.   typedef struct {
  2042.     USHORT Filler ;
  2043.     USHORT fs ;
  2044.     USHORT cy, cx, y, x ;
  2045.     HWND hwndInsertBehind ;
  2046.     HWND hwnd ;
  2047.   } OLDSWP ;
  2048.   #pragma pack()
  2049.  
  2050.   ULONG Size ;
  2051.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  2052.   Profile->fPosition = FALSE ;
  2053.   if ( PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &Size ) )
  2054.   {
  2055.     if ( Size == sizeof(OLDSWP)-sizeof(USHORT) )
  2056.     {
  2057.       OLDSWP OldPosition ;
  2058.       if ( PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &OldPosition.fs, &Size ) )
  2059.       {
  2060.         Profile->Position.fl = OldPosition.fs ;
  2061.         Profile->Position.cy = OldPosition.cy ;
  2062.         Profile->Position.cx = OldPosition.cx ;
  2063.         Profile->Position.y = OldPosition.y ;
  2064.         Profile->Position.x = OldPosition.x ;
  2065.         Profile->Position.hwndInsertBehind = OldPosition.hwndInsertBehind ;
  2066.         Profile->Position.hwnd = OldPosition.hwnd ;
  2067.         Profile->fPosition = TRUE ;
  2068.       }
  2069.     }
  2070.     else if ( Size == sizeof(Profile->Position) )
  2071.     {
  2072.       if ( PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Position", &Profile->Position, &Size ) )
  2073.       {
  2074.         Profile->fPosition = TRUE ;
  2075.       }
  2076.     }
  2077.   }
  2078.  
  2079.   if ( NOT Profile->fPosition )
  2080.   {
  2081.     if ( ProfileHandle == HINI_USERPROFILE )
  2082.     {
  2083.       return ( 1 ) ;
  2084.     }
  2085.   }
  2086.  
  2087.  /***************************************************************************
  2088.   * Get the program options.                            *
  2089.   ***************************************************************************/
  2090.  
  2091.   Profile->HideControls = FALSE ;
  2092.   Profile->fHideControls = FALSE ;
  2093.   if 
  2094.   ( 
  2095.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"HideControls", &Size )
  2096.     AND
  2097.     ( ( Size == sizeof(Profile->HideControls) ) OR ( Size == sizeof(short) ) )
  2098.     AND
  2099.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"HideControls", &Profile->HideControls, &Size )
  2100.   )
  2101.   {
  2102.     Profile->fHideControls = TRUE ;
  2103.   }
  2104.  
  2105.   Profile->Float = FALSE ;
  2106.   Profile->fFloat = FALSE ;
  2107.   if 
  2108.   ( 
  2109.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Float", &Size )
  2110.     AND
  2111.     ( ( Size == sizeof(Profile->Float) ) OR ( Size == sizeof(short) ) )
  2112.     AND
  2113.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"Float", &Profile->Float, &Size )
  2114.   )
  2115.   {
  2116.     Profile->fFloat = TRUE ;
  2117.   }
  2118.  
  2119.   Profile->TimerInterval = 1000 ;
  2120.   Profile->fTimerInterval = FALSE ;
  2121.   if 
  2122.   ( 
  2123.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"TimerInterval", &Size )
  2124.     AND
  2125.     ( ( Size == sizeof(Profile->TimerInterval) ) OR ( Size == sizeof(short) ) )
  2126.     AND
  2127.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"TimerInterval", &Profile->TimerInterval, &Size ) 
  2128.   )
  2129.   {
  2130.     Profile->fTimerInterval = TRUE ;
  2131.   }
  2132.  
  2133.  /***************************************************************************
  2134.   * Get the presentation parameters.                        *
  2135.   ***************************************************************************/
  2136.  
  2137.   strcpy ( (PCHAR)Profile->FontNameSize, "" ) ;
  2138.   Profile->fFontNameSize = FALSE ;
  2139.   if
  2140.   (
  2141.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", &Size )
  2142.     AND
  2143.     ( Size == sizeof(Profile->FontNameSize) )
  2144.     AND
  2145.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"FontNameSize", &Profile->FontNameSize, &Size )
  2146.   )
  2147.   {
  2148.     Profile->fFontNameSize = TRUE ;
  2149.   }
  2150.  
  2151.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  2152.   Profile->fBackColor = FALSE ;
  2153.   if
  2154.   (
  2155.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", &Size )
  2156.     AND
  2157.     ( Size == sizeof(Profile->BackColor) )
  2158.     AND
  2159.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"BackgroundColor", &Profile->BackColor, &Size )
  2160.   )
  2161.   {
  2162.     Profile->fBackColor = TRUE ;
  2163.   }
  2164.  
  2165.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  2166.   Profile->fTextColor = FALSE ;
  2167.   if
  2168.   (
  2169.     PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", &Size )
  2170.     AND
  2171.     ( Size == sizeof(Profile->TextColor) )
  2172.     AND
  2173.     PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, (PSZ)"ForegroundColor", &Profile->TextColor, &Size )
  2174.   )
  2175.   {
  2176.     Profile->fTextColor = TRUE ;
  2177.   }
  2178.  
  2179.  /***************************************************************************
  2180.   * Build the fixed portion of the item list.                    *
  2181.   ***************************************************************************/
  2182.  
  2183.   ResourceString ClockLabel ( Library, IDS_SHOW_CLOCK_LABEL ) ;
  2184.   ResourceString ClockOption ( Library, IDS_SHOW_CLOCK_OPTION ) ;
  2185.   Profile->Items[ITEM_CLOCK] = new Clock ( ITEM_CLOCK,
  2186.     PSZ("ShowClock"), ClockLabel.Ptr(), ClockOption.Ptr(),
  2187.     Profile->CountryInfo, Profile->DaysOfWeek ) ;
  2188.  
  2189.   ResourceString ElapsedLabel ( Library, IDS_SHOW_ELAPSED_LABEL ) ;
  2190.   ResourceString ElapsedOption ( Library, IDS_SHOW_ELAPSED_OPTION ) ;
  2191.   Profile->Items[ITEM_ELAPSEDTIME] = new ElapsedTime ( ITEM_ELAPSEDTIME,
  2192.     PSZ("ShowElapsed"), ElapsedLabel.Ptr(), ElapsedOption.Ptr(),
  2193.     Profile->CountryInfo,
  2194.     Profile->Day,
  2195.     Profile->Days ) ;
  2196.  
  2197.   ResourceString SwapSizeLabel ( Library, IDS_SHOW_SWAPSIZE_LABEL ) ;
  2198.   ResourceString SwapSizeOption ( Library, IDS_SHOW_SWAPSIZE_OPTION ) ;
  2199.   Profile->Items[ITEM_SWAPFILESIZE] = new SwapSize ( ITEM_SWAPFILESIZE,
  2200.     PSZ("ShowSwapsize"), SwapSizeLabel.Ptr(), SwapSizeOption.Ptr(),
  2201.     Profile->CountryInfo,
  2202.     Profile->SwapPath ) ;
  2203.  
  2204.   ResourceString SwapFreeLabel ( Library, IDS_SHOW_SWAPFREE_LABEL ) ;
  2205.   ResourceString SwapFreeOption ( Library, IDS_SHOW_SWAPFREE_OPTION ) ;
  2206.   Profile->Items[ITEM_SWAPDISKFREE] = new SwapFree ( ITEM_SWAPDISKFREE,
  2207.     PSZ("ShowSwapfree"), SwapFreeLabel.Ptr(), SwapFreeOption.Ptr(),
  2208.     Profile->CountryInfo,
  2209.     Profile->SwapPath,
  2210.     Profile->MinFree ) ;
  2211.  
  2212.   ResourceString MemoryLabel ( Library, IDS_SHOW_MEMORY_LABEL ) ;
  2213.   ResourceString MemoryOption ( Library, IDS_SHOW_MEMORY_OPTION ) ;
  2214.   Profile->Items[ITEM_MEMORYFREE] = new MemoryFree ( ITEM_MEMORYFREE,
  2215.     PSZ("ShowMemory"), MemoryLabel.Ptr(), MemoryOption.Ptr(),
  2216.     Profile->CountryInfo,
  2217.     (SwapFree*)Profile->Items[ITEM_SWAPDISKFREE] ) ;
  2218.  
  2219.   ResourceString SpoolSizeLabel ( Library, IDS_SHOW_SPOOLSIZE_LABEL ) ;
  2220.   ResourceString SpoolSizeOption ( Library, IDS_SHOW_SPOOLSIZE_OPTION ) ;
  2221.   Profile->Items[ITEM_SPOOLFILESIZE] = new SpoolSize ( ITEM_SPOOLFILESIZE,
  2222.     PSZ("ShowSpoolSize"), SpoolSizeLabel.Ptr(), SpoolSizeOption.Ptr(),
  2223.     Profile->CountryInfo,
  2224.     Profile->SpoolPath ) ;
  2225.  
  2226.   ResourceString CpuLoadLabel ( Library, IDS_SHOW_CPULOAD_LABEL ) ;
  2227.   ResourceString CpuLoadOption ( Library, IDS_SHOW_CPULOAD_OPTION ) ;
  2228.   Profile->Items[ITEM_CPULOAD] = new CpuLoad ( ITEM_CPULOAD,
  2229.     PSZ("ShowCpuLoad"), CpuLoadLabel.Ptr(), CpuLoadOption.Ptr(),
  2230.     Profile->MaxCount,
  2231.     &Profile->IdleCount ) ;
  2232.  
  2233.   ResourceString TaskCountLabel ( Library, IDS_SHOW_TASKCOUNT_LABEL ) ;
  2234.   ResourceString TaskCountOption ( Library, IDS_SHOW_TASKCOUNT_OPTION ) ;
  2235.   Profile->Items[ITEM_TASKCOUNT] = new TaskCount ( ITEM_TASKCOUNT,
  2236.     PSZ("ShowTaskCount"), TaskCountLabel.Ptr(), TaskCountOption.Ptr(),
  2237.     Anchor ) ;
  2238.  
  2239.   ResourceString TotalFreeLabel ( Library, IDS_SHOW_TOTALFREE_LABEL ) ;
  2240.   ResourceString TotalFreeOption ( Library, IDS_SHOW_TOTALFREE_OPTION ) ;
  2241.   Profile->Items[ITEM_TOTALFREE] = new TotalFree ( ITEM_TOTALFREE,
  2242.     PSZ("ShowTotalFree"), TotalFreeLabel.Ptr(), TotalFreeOption.Ptr(),
  2243.     Profile->CountryInfo, 0 ) ;
  2244.  
  2245.   for ( int i=0; i<ITEM_BASE_COUNT; i++ )
  2246.   {
  2247.     BOOL Flag = TRUE ;
  2248.     if 
  2249.     ( 
  2250.       PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, Profile->Items[i]->QueryName(), &Size )
  2251.       AND
  2252.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  2253.       AND 
  2254.       PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, Profile->Items[i]->QueryName(), &Flag, &Size )
  2255.     )
  2256.     {
  2257.       ;
  2258.     }
  2259.  
  2260.     if ( Flag )
  2261.       Profile->Items[i]->SetFlag() ;
  2262.     else
  2263.       Profile->Items[i]->ResetFlag() ;
  2264.   }
  2265.  
  2266.  /***************************************************************************
  2267.   * Add items for each drive on the system.                    *
  2268.   ***************************************************************************/
  2269.  
  2270.   ULONG Drive, Drives ;
  2271.   DosQueryCurrentDisk ( &Drive, &Drives ) ;
  2272.   UpdateDriveList ( Anchor, Library, ProfileHandle, Profile, 0, Drives ) ;
  2273.  
  2274.   return ( 0 ) ;
  2275. }
  2276.  
  2277. /****************************************************************************
  2278.  *                                        *
  2279.  *                 Put Profile Data                    *
  2280.  *                                        *
  2281.  ****************************************************************************/
  2282.  
  2283. STATIC void PutProfile ( HINI ProfileHandle, PPROFILE Profile )
  2284. {
  2285.  /***************************************************************************
  2286.   * Save the window's current size and position.                            *
  2287.   ***************************************************************************/
  2288.  
  2289.   PrfWriteProfileData
  2290.   (
  2291.     ProfileHandle,
  2292.     (PSZ)PROGRAM_NAME,
  2293.     (PSZ)"Position",
  2294.     &Profile->Position,
  2295.     sizeof(Profile->Position)
  2296.   ) ;
  2297.  
  2298.  /***************************************************************************
  2299.   * Save the program options.                            *
  2300.   ***************************************************************************/
  2301.  
  2302.   if ( Profile->fHideControls )
  2303.   {
  2304.     PrfWriteProfileData
  2305.     (
  2306.       ProfileHandle,
  2307.       (PSZ)PROGRAM_NAME,
  2308.       (PSZ)"HideControls",
  2309.       &Profile->HideControls,
  2310.       sizeof(Profile->HideControls)
  2311.     ) ;
  2312.   }
  2313.  
  2314.   if ( Profile->fFloat )
  2315.   {
  2316.     PrfWriteProfileData
  2317.     (
  2318.       ProfileHandle,
  2319.       (PSZ)PROGRAM_NAME,
  2320.       (PSZ)"Float",
  2321.       &Profile->Float,
  2322.       sizeof(Profile->Float)
  2323.     ) ;
  2324.   }
  2325.  
  2326.   if ( Profile->fTimerInterval )
  2327.   {
  2328.     PrfWriteProfileData
  2329.     (
  2330.       ProfileHandle,
  2331.       (PSZ)PROGRAM_NAME,
  2332.       (PSZ)"TimerInterval",
  2333.       &Profile->TimerInterval,
  2334.       sizeof(Profile->TimerInterval)
  2335.     ) ;
  2336.   }
  2337.  
  2338.  /***************************************************************************
  2339.   * Save the item options.                            *
  2340.   ***************************************************************************/
  2341.  
  2342.   for ( int i=0; i<Profile->ItemCount; i++ )
  2343.   {
  2344.     Item *pItem = Profile->Items [i] ;
  2345.     BOOL Flag = pItem->QueryFlag() ;
  2346.  
  2347.     PrfWriteProfileData
  2348.     (
  2349.       ProfileHandle,
  2350.       PSZ(PROGRAM_NAME),
  2351.       pItem->QueryName(),
  2352.       &Flag,
  2353.       sizeof(Flag)
  2354.     ) ;
  2355.   }
  2356.  
  2357.  /***************************************************************************
  2358.   * Save the presentation parameters.                        *
  2359.   ***************************************************************************/
  2360.  
  2361.   if ( Profile->fFontNameSize )
  2362.   {
  2363.     PrfWriteProfileData
  2364.     (
  2365.       ProfileHandle,
  2366.       (PSZ)PROGRAM_NAME,
  2367.       (PSZ)"FontNameSize",
  2368.       Profile->FontNameSize,
  2369.       sizeof(Profile->FontNameSize)
  2370.     ) ;
  2371.   }
  2372.  
  2373.   if ( Profile->fBackColor )
  2374.   {
  2375.     PrfWriteProfileData
  2376.     (
  2377.       ProfileHandle,
  2378.       (PSZ)PROGRAM_NAME,
  2379.       (PSZ)"BackgroundColor",
  2380.       &Profile->BackColor,
  2381.       sizeof(Profile->BackColor)
  2382.     ) ;
  2383.   }
  2384.  
  2385.   if ( Profile->fTextColor )
  2386.   {
  2387.     PrfWriteProfileData
  2388.     (
  2389.       ProfileHandle,
  2390.       (PSZ)PROGRAM_NAME,
  2391.       (PSZ)"ForegroundColor",
  2392.       &Profile->TextColor,
  2393.       sizeof(Profile->TextColor)
  2394.     ) ;
  2395.   }
  2396. }
  2397.  
  2398. /****************************************************************************
  2399.  *                                        *
  2400.  *    Scan CONFIG.SYS for a keyword.    Return the value.            *
  2401.  *                                        *
  2402.  ****************************************************************************/
  2403.  
  2404. STATIC PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword )
  2405. {
  2406.  /***************************************************************************
  2407.   * Get the boot drive number from the global information segment.        *
  2408.   ***************************************************************************/
  2409.  
  2410.   ULONG BootDrive ;
  2411.   DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
  2412.  
  2413.  /***************************************************************************
  2414.   * Convert the keyword to upper case.                                      *
  2415.   ***************************************************************************/
  2416.  
  2417.   WinUpper ( Anchor, NULL, NULL, Keyword ) ;
  2418.  
  2419.  /***************************************************************************
  2420.   * Build the CONFIG.SYS path.                            *
  2421.   ***************************************************************************/
  2422.  
  2423.   char Path [_MAX_PATH] ;
  2424.   Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
  2425.   Path[1] = 0 ;
  2426.   strcat ( Path, ":\\CONFIG.SYS" ) ;
  2427.  
  2428.  /***************************************************************************
  2429.   * Open CONFIG.SYS for reading.                        *
  2430.   ***************************************************************************/
  2431.  
  2432.   FILE *File = fopen ( Path, "r" ) ;
  2433.   if ( NOT File )
  2434.   {
  2435.     return ( NULL ) ;
  2436.   }
  2437.  
  2438.  /***************************************************************************
  2439.   * While there're more lines in CONFIG.SYS, read a line and check it.      *
  2440.   ***************************************************************************/
  2441.  
  2442.   static char Buffer [500] ;
  2443.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  2444.   {
  2445.  
  2446.    /*************************************************************************
  2447.     * Clean any trailing newline character from the input string.        *
  2448.     *************************************************************************/
  2449.  
  2450.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  2451.     {
  2452.       Buffer[strlen(Buffer)-1] = 0 ;
  2453.     }
  2454.  
  2455.    /*************************************************************************
  2456.     * If keyword starts the line, we've found the line we want.  Close      *
  2457.     *    the file and return a pointer to the parameter text.            *
  2458.     *************************************************************************/
  2459.  
  2460.     WinUpper ( Anchor, NULL, NULL, (PSZ)Buffer ) ;
  2461.  
  2462.     if ( NOT strncmp ( Buffer, (PCHAR)Keyword, strlen((PCHAR)Keyword) )
  2463.       AND ( Buffer[strlen((PCHAR)Keyword)] == '=' ) )
  2464.     {
  2465.       fclose ( File ) ;
  2466.       return ( (PSZ) ( Buffer + strlen((PCHAR)Keyword) + 1 ) ) ;
  2467.     }
  2468.   }
  2469.  
  2470.  /***************************************************************************
  2471.   * Close the file.  We haven't found the line we wanted.                   *
  2472.   ***************************************************************************/
  2473.  
  2474.   fclose ( File ) ;
  2475.  
  2476.   return ( NULL ) ;
  2477. }
  2478.  
  2479. /****************************************************************************
  2480.  *                                        *
  2481.  *             Resize Client Window                    *
  2482.  *                                        *
  2483.  ****************************************************************************/
  2484.  
  2485. STATIC void ResizeWindow ( HWND hwnd, PPROFILE Profile )
  2486. {
  2487.  /***************************************************************************
  2488.   * If the window is visible and minimized, restore it invisibly.        *
  2489.   ***************************************************************************/
  2490.  
  2491.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT ) ;
  2492.  
  2493.   SHORT fHadToHide = FALSE ;
  2494.   SHORT fHadToRestore = FALSE ;
  2495.   if ( Profile->Position.fl & SWP_MINIMIZE )
  2496.   {
  2497.     if ( WinIsWindowVisible ( hwndFrame ) )
  2498.     {
  2499.       WinShowWindow ( hwndFrame, FALSE ) ;
  2500.       fHadToHide = TRUE ;
  2501.     }
  2502.     WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE ) ;
  2503.     fHadToRestore = TRUE ;
  2504.   }
  2505.  
  2506.  /***************************************************************************
  2507.   * Determine how many items are to be displayed.                *
  2508.   ***************************************************************************/
  2509.  
  2510.   HPS hPS = WinGetPS ( hwnd ) ;
  2511.  
  2512.   int Count = 0 ;
  2513.   LONG Widest = 0 ;
  2514.   LONG Height = 0 ;
  2515.  
  2516.   for ( int i=0; i<Profile->ItemCount; i++ )
  2517.   {
  2518.     Item *pItem = Profile->Items [i] ;
  2519.  
  2520.     if ( pItem->QueryFlag() )
  2521.     {
  2522.       Count ++ ;
  2523.  
  2524.       BYTE Text [100] ;
  2525.       sprintf ( (PCHAR)Text, "%s 1,234,567K", pItem->QueryLabel() ) ;
  2526.  
  2527.       RECTL Rectangle ;
  2528.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  2529.  
  2530.       WinDrawText ( hPS, strlen((PCHAR)Text), Text,
  2531.     &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  2532.  
  2533.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft+1) ) ;
  2534.  
  2535.       Height += Rectangle.yTop - Rectangle.yBottom ;
  2536.     }
  2537.   }
  2538.  
  2539.   WinReleasePS ( hPS ) ;
  2540.  
  2541.  /***************************************************************************
  2542.   * Get the window's current size & position.                               *
  2543.   ***************************************************************************/
  2544.  
  2545.   RECTL Rectangle ;
  2546.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  2547.  
  2548.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2549.  
  2550.  /***************************************************************************
  2551.   * Adjust the window's width & height.                                     *
  2552.   ***************************************************************************/
  2553.  
  2554.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  2555.  
  2556.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  2557.  
  2558.  /***************************************************************************
  2559.   * Compute new frame size and apply it.                    *
  2560.   ***************************************************************************/
  2561.  
  2562.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2563.  
  2564.   WinSetWindowPos ( hwndFrame, NULL, 0, 0,
  2565.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2566.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2567.     SWP_SIZE ) ;
  2568.  
  2569.  /***************************************************************************
  2570.   * Return the window to its original state.                    *
  2571.   ***************************************************************************/
  2572.  
  2573.   if ( fHadToRestore )
  2574.   {
  2575.     WinSetWindowPos ( hwndFrame, NULL,
  2576.       Profile->Position.x, Profile->Position.y,
  2577.       Profile->Position.cx, Profile->Position.cy,
  2578.       SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
  2579.   }
  2580.  
  2581.   if ( fHadToHide )
  2582.   {
  2583.     WinShowWindow ( hwndFrame, TRUE ) ;
  2584.   }
  2585.  
  2586.  /***************************************************************************
  2587.   * Invalidate the window so that it gets repainted.                *
  2588.   ***************************************************************************/
  2589.  
  2590.   WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  2591. }
  2592.  
  2593. /****************************************************************************
  2594.  *                                        *
  2595.  *            Hide Window Controls                    *
  2596.  *                                        *
  2597.  ****************************************************************************/
  2598.  
  2599. STATIC void HideControls
  2600. (
  2601.   BOOL fHide,
  2602.   HWND hwndFrame,
  2603.   HWND hwndSysMenu,
  2604.   HWND hwndTitleBar,
  2605.   HWND hwndMinMax
  2606. )
  2607. {
  2608.  /***************************************************************************
  2609.   * Get original window position and state.                    *
  2610.   ***************************************************************************/
  2611.  
  2612.   SWP OldPosition ;
  2613.   WinQueryWindowPos ( hwndFrame, &OldPosition ) ;
  2614.  
  2615.   BOOL WasVisible = WinIsWindowVisible ( hwndFrame ) ;
  2616.  
  2617.  /***************************************************************************
  2618.   * Restore and hide the window.                        *
  2619.   ***************************************************************************/
  2620.  
  2621.   WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE | SWP_HIDE ) ;
  2622.  
  2623.  /***************************************************************************
  2624.   * Determine client window and location.                    *
  2625.   ***************************************************************************/
  2626.  
  2627.   SWP Position ;
  2628.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  2629.  
  2630.   RECTL Rectangle ;
  2631.   Rectangle.xLeft   = Position.x ;
  2632.   Rectangle.xRight  = Position.x + Position.cx ;
  2633.   Rectangle.yBottom = Position.y ;
  2634.   Rectangle.yTop    = Position.y + Position.cy ;
  2635.  
  2636.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2637.  
  2638.  /***************************************************************************
  2639.   * Hide or reveal the controls windows by changing their parentage.        *
  2640.   ***************************************************************************/
  2641.  
  2642.   if ( fHide )
  2643.   {
  2644.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2645.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2646.     WinSetParent ( hwndMinMax,     HWND_OBJECT, FALSE ) ;
  2647.   }
  2648.   else
  2649.   {
  2650.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2651.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2652.     WinSetParent ( hwndMinMax,     hwndFrame, TRUE ) ;
  2653.   }
  2654.  
  2655.  /***************************************************************************
  2656.   * Tell the frame that things have changed.  Let it update the window.     *
  2657.   ***************************************************************************/
  2658.  
  2659.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2660.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2661.  
  2662.  /***************************************************************************
  2663.   * Reposition the frame around the client window, which is left be.        *
  2664.   ***************************************************************************/
  2665.  
  2666.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2667.  
  2668.   WinSetWindowPos ( hwndFrame, NULL,
  2669.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2670.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2671.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2672.     SWP_SIZE | SWP_MOVE ) ;
  2673.  
  2674.  /***************************************************************************
  2675.   * If window was maximized, put it back that way.                *
  2676.   ***************************************************************************/
  2677.  
  2678.   if ( OldPosition.fl & SWP_MAXIMIZE )
  2679.   {
  2680.     WinSetWindowPos ( hwndFrame, NULL,
  2681.       (SHORT) Rectangle.xLeft,    (SHORT) Rectangle.yBottom,
  2682.       (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2683.       (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2684.       SWP_SIZE | SWP_MOVE |
  2685.       ( OldPosition.fl & SWP_MAXIMIZE ) ) ;
  2686.   }
  2687.  
  2688.  /***************************************************************************
  2689.   * If the window was visible in the first place, show it.            *
  2690.   ***************************************************************************/
  2691.  
  2692.   if ( WasVisible )
  2693.   {
  2694.     WinShowWindow ( hwndFrame, TRUE ) ;
  2695.   }
  2696. }
  2697.  
  2698. /****************************************************************************
  2699.  *                                        *
  2700.  *    Update Window                                *
  2701.  *                                        *
  2702.  ****************************************************************************/
  2703.  
  2704. STATIC void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All )
  2705. {
  2706.  /***************************************************************************
  2707.   * Determine how many items are to be displayed.                *
  2708.   ***************************************************************************/
  2709.  
  2710.   int Count = 0 ;
  2711.   for ( int i=0; i<Data->Profile.ItemCount; i++ )
  2712.   {
  2713.     if ( Data->Profile.Items[i]->QueryFlag() )
  2714.     {
  2715.       Count ++ ;
  2716.     }
  2717.   }
  2718.  
  2719.  /***************************************************************************
  2720.   * Get presentation space and make it use RGB colors.                *
  2721.   ***************************************************************************/
  2722.  
  2723.   HPS hPS = WinGetPS ( hwnd ) ;
  2724.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  2725.  
  2726.  /***************************************************************************
  2727.   * Get the window's size and determine the initial position.               *
  2728.   ***************************************************************************/
  2729.  
  2730.   RECTL Rectangle ;
  2731.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2732.  
  2733.   Rectangle.xLeft += Data->Width / 2 ;
  2734.   Rectangle.xRight -= Data->Width / 2 ;
  2735.  
  2736.   Rectangle.yBottom = Data->Height * ( Count - 1 ) ;
  2737.   Rectangle.yTop = Rectangle.yBottom + Data->Height ;
  2738.  
  2739.  /***************************************************************************
  2740.   * Review all items.  Display those changed, or all.                *
  2741.   ***************************************************************************/
  2742.  
  2743.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2744.   {
  2745.     ULONG NewValue ;
  2746.  
  2747.     Item *pItem = Data->Profile.Items [i] ;
  2748.  
  2749.     if ( pItem->QueryFlag() )
  2750.     {
  2751.       pItem->Repaint ( hPS, Rectangle,
  2752.     Data->Profile.TextColor, Data->Profile.BackColor, All ) ;
  2753.  
  2754.       Rectangle.yBottom -= Data->Height ;
  2755.       Rectangle.yTop    -= Data->Height ;
  2756.     }
  2757.   }
  2758.  
  2759.  /***************************************************************************
  2760.   * Release the presentation space and return.                    *
  2761.   ***************************************************************************/
  2762.  
  2763.   WinReleasePS ( hPS ) ;
  2764. }
  2765.  
  2766.  
  2767. /****************************************************************************
  2768.  *                                        *
  2769.  *    Monitor Loop Thread                            *
  2770.  *                                        *
  2771.  ****************************************************************************/
  2772.  
  2773. STATIC VOID MonitorLoopThread ( ULONG Parameter )
  2774. {
  2775.  /***************************************************************************
  2776.   * Get the thread parameter.                                               *
  2777.   ***************************************************************************/
  2778.  
  2779.   PMONITOR_PARMS Parms = PMONITOR_PARMS ( Parameter ) ;
  2780.  
  2781.  /***************************************************************************
  2782.   * Set this thread's priority as high as it can go.                        *
  2783.   ***************************************************************************/
  2784.  
  2785.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  2786.  
  2787.  /***************************************************************************
  2788.   * Start up the high resolution timer, if it is available.            *
  2789.   ***************************************************************************/
  2790.  
  2791.   BOOL HiResTimer = OpenTimer ( ) ;
  2792.  
  2793.  /***************************************************************************
  2794.   * Loop forever . . .                                *
  2795.   ***************************************************************************/
  2796.  
  2797.   while ( 1 )
  2798.   {
  2799.  
  2800.    /*************************************************************************
  2801.     * Reset the last time and count seen.                    *
  2802.     *************************************************************************/
  2803.  
  2804.     ULONG LastMilliseconds ;
  2805.     TIMESTAMP Time [2] ;
  2806.  
  2807.     if ( HiResTimer )
  2808.       GetTime ( &Time[0] ) ;
  2809.     else
  2810.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &LastMilliseconds, sizeof(LastMilliseconds) ) ;
  2811.  
  2812.     ULONG LastCounter = *Parms->Counter ;
  2813.  
  2814.    /*************************************************************************
  2815.     * Sleep for a bit.                                *
  2816.     *************************************************************************/
  2817.  
  2818.     DosSleep ( *Parms->Interval ) ;
  2819.  
  2820.    /*************************************************************************
  2821.     * Find out how much time and counts went by.                *
  2822.     *************************************************************************/
  2823.  
  2824.     ULONG CurrentCounter = *Parms->Counter ;
  2825.  
  2826.     ULONG DeltaMilliseconds ;
  2827.  
  2828.     if ( HiResTimer )
  2829.     {
  2830.       GetTime ( &Time[1] ) ;
  2831.  
  2832.       ULONG Nanoseconds ;
  2833.       DeltaMilliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  2834.  
  2835.       if ( Nanoseconds >= 500000L )
  2836.     DeltaMilliseconds ++ ;
  2837.     }
  2838.     else
  2839.     {
  2840.       ULONG Milliseconds ;
  2841.       DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
  2842.       DeltaMilliseconds = Milliseconds - LastMilliseconds ;
  2843.     }
  2844.  
  2845.    /*************************************************************************
  2846.     * Find out how much idle time was counted.    Adjust it to persecond.     *
  2847.     *************************************************************************/
  2848.  
  2849.     ULONG Counter = (ULONG) ( ( (double)(CurrentCounter-LastCounter) * 1000L ) / (double)DeltaMilliseconds ) ;
  2850.  
  2851.    /*************************************************************************
  2852.     * Tell the owner window to refresh its statistics.                *
  2853.     *************************************************************************/
  2854.  
  2855.     WinPostMsg ( Parms->Owner, WM_REFRESH, MPFROMLONG(Counter), 0L ) ;
  2856.   }
  2857. }
  2858.  
  2859. /****************************************************************************
  2860.  *                                        *
  2861.  *    Update the Item List to reflect changes in the available drives.    *
  2862.  *                                        *
  2863.  ****************************************************************************/
  2864.  
  2865. STATIC VOID UpdateDriveList
  2866. (
  2867.   HAB Anchor,
  2868.   HMODULE Library,
  2869.   HINI ProfileHandle,
  2870.   PPROFILE Profile,
  2871.   ULONG OldDrives,
  2872.   ULONG NewDrives
  2873. )
  2874. {
  2875.  /***************************************************************************
  2876.   * Get format strings.                             *
  2877.   ***************************************************************************/
  2878.  
  2879.   ResourceString LabelFormat ( Library, IDS_SHOW_DRIVE_FREE_LABEL ) ;
  2880.   ResourceString OptionFormat ( Library, IDS_SHOW_DRIVE_FREE_OPTION ) ;
  2881.  
  2882.  /***************************************************************************
  2883.   * Save the old item list for comparison.                    *
  2884.   ***************************************************************************/
  2885.  
  2886.   Item *OldItems [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  2887.  
  2888.   memset ( OldItems, 0, sizeof(OldItems) ) ;
  2889.  
  2890.   USHORT OldCount = 0 ;
  2891.   if ( OldDrives )
  2892.   {
  2893.     OldCount = Profile->ItemCount ;
  2894.     memcpy ( OldItems, Profile->Items, sizeof(OldItems) ) ;
  2895.   }
  2896.  
  2897.  /***************************************************************************
  2898.   * Add items for each drive on the system.                    *
  2899.   ***************************************************************************/
  2900.  
  2901.   USHORT Count = ITEM_BASE_COUNT ;
  2902.   USHORT OldIndex = ITEM_BASE_COUNT ;
  2903.  
  2904.   ULONG Drives = 0 ;
  2905.   NewDrives >>= 2 ;
  2906.   OldDrives >>= 2 ;
  2907.  
  2908.   for ( int Drive=3; Drive<=MAX_DRIVES; Drive++ )
  2909.   {
  2910.     while ( ( OldIndex < OldCount )
  2911.       AND ( (SHORT)OldItems[OldIndex]->QueryId() < ITEM_BASE_COUNT + Drive ) )
  2912.     {
  2913.       OldIndex ++ ;
  2914.     }
  2915.  
  2916.     if ( NewDrives & 1 )
  2917.     {
  2918.       if ( OldDrives & 1 )
  2919.       {
  2920.     Drives |= ( 1 << (Drive-1) ) ;
  2921.     if ( ( OldIndex < OldCount )
  2922.       AND ( (SHORT)OldItems[OldIndex]->QueryId() == ITEM_BASE_COUNT + Drive ) )
  2923.     {
  2924.       Profile->Items[Count++] = OldItems[OldIndex++] ;
  2925.     }
  2926.       }
  2927.       else
  2928.       {
  2929.         BYTE FileSystem [80] ;
  2930.     if ( CheckDrive ( Drive, FileSystem ) )
  2931.     {
  2932.       Drives |= ( 1 << (Drive-1) ) ;
  2933.  
  2934.       BYTE Name [80] ;
  2935.       sprintf ( PCHAR(Name),   "ShowDrive%c:", Drive+'A'-1 ) ;
  2936.  
  2937.       BYTE Label [80] ;
  2938.       sprintf ( PCHAR(Label),  (PCHAR)LabelFormat.Ptr(),  Drive+'A'-1, FileSystem ) ;
  2939.  
  2940.       BYTE Option [80] ;
  2941.       sprintf ( PCHAR(Option), (PCHAR)OptionFormat.Ptr(), Drive+'A'-1 ) ;
  2942.  
  2943.       Profile->Items[Count++] = new DriveFree ( ITEM_BASE_COUNT+Drive,
  2944.         Name, Label, Option, Profile->CountryInfo,
  2945.         Drive, Profile->DriveError ) ;
  2946.     }
  2947.       }
  2948.     }
  2949.     else
  2950.     {
  2951.       if ( OldDrives & 1 )
  2952.       {
  2953.     delete OldItems[OldIndex++] ;
  2954.       }
  2955.       else
  2956.       {
  2957.     // Do nothing.
  2958.       }
  2959.     }
  2960.  
  2961.     NewDrives >>= 1 ;
  2962.     OldDrives >>= 1 ;
  2963.   }
  2964.  
  2965.  /***************************************************************************
  2966.   * Save the new item count.                            *
  2967.   ***************************************************************************/
  2968.  
  2969.   Profile->ItemCount = Count ;
  2970.  
  2971.  /***************************************************************************
  2972.   * Fetch the display flags for the drives.                    *
  2973.   ***************************************************************************/
  2974.  
  2975.   for ( int i=ITEM_BASE_COUNT; i<Profile->ItemCount; i++ )
  2976.   {
  2977.     BOOL Flag = TRUE ;
  2978.     Item *pItem = Profile->Items [i] ;
  2979.     ULONG Size ;
  2980.  
  2981.     if
  2982.     (
  2983.       PrfQueryProfileSize ( ProfileHandle, (PSZ)PROGRAM_NAME, pItem->QueryName(), &Size )
  2984.       AND
  2985.       ( ( Size == sizeof(Flag) ) OR ( Size == sizeof(short) ) )
  2986.       AND
  2987.       PrfQueryProfileData ( ProfileHandle, (PSZ)PROGRAM_NAME, pItem->QueryName(), &Flag, &Size )
  2988.     )
  2989.     {
  2990.       ;
  2991.     }
  2992.  
  2993.     if ( Flag )
  2994.       pItem->SetFlag () ;
  2995.     else
  2996.       pItem->ResetFlag () ;
  2997.   }
  2998.  
  2999.  /***************************************************************************
  3000.   * Update the total free space object.                     *
  3001.   ***************************************************************************/
  3002.  
  3003.   ( (TotalFree*) Profile->Items [ ITEM_TOTALFREE ] ) -> ResetMask ( Drives ) ;
  3004. }
  3005.  
  3006. /****************************************************************************
  3007.  *                                        *
  3008.  *    Check to see if drive should be added to display list.            *
  3009.  *                                        *
  3010.  ****************************************************************************/
  3011.  
  3012. STATIC BOOL CheckDrive ( USHORT Drive, PBYTE FileSystem )
  3013. {
  3014.  /***************************************************************************
  3015.   * First, check to see if drive is local or remote.  Remote drives are     *
  3016.   *   always monitored.                             *
  3017.   ***************************************************************************/
  3018.  
  3019.   BYTE Path [3] ;
  3020.   Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  3021.   Path[1] = ':' ;
  3022.   Path[2] = 0 ;
  3023.  
  3024.   DosError ( FERR_DISABLEHARDERR ) ;
  3025.  
  3026.   BYTE Buffer [1024] ;
  3027.   ULONG Size = sizeof(Buffer) ;
  3028.   ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
  3029.   DosError ( FERR_ENABLEHARDERR ) ;
  3030.  
  3031.   if ( Status )
  3032.   {
  3033. //  Log ( "ERROR: Unable to query drive %s for file system.  Status %04X.\r\n",
  3034. //    Path, Status ) ;
  3035.     return ( FALSE ) ;
  3036.   }
  3037.  
  3038.   USHORT cbName = ((PFSQBUFFER2)Buffer)->cbName ;
  3039.   strcpy ( (PCHAR)FileSystem, (PCHAR)((PFSQBUFFER2)(Buffer+cbName))->szFSDName ) ;
  3040.  
  3041.   if ( ((PFSQBUFFER2)Buffer)->iType == FSAT_REMOTEDRV )
  3042.   {
  3043.     return ( TRUE ) ;
  3044.   }
  3045.  
  3046.  /***************************************************************************
  3047.   * Attempt to open the local drive as an entire device.  If unable to do   *
  3048.   *   so, we cannot monitor this drive.                     *
  3049.   ***************************************************************************/
  3050.  
  3051.   ULONG Action ;
  3052.   HFILE Handle ;
  3053.   Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  3054.     OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  3055.     OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  3056.  
  3057.   if ( Status )
  3058.   {
  3059. //  Log ( "ERROR: Unable to open local drive %s.  Status %04X.\r\n",
  3060. //    Path, Status ) ;
  3061.     return ( FALSE ) ;
  3062.   }
  3063.  
  3064.  /***************************************************************************
  3065.   * Check to see if the drive has removable media.  We cannot monitor such. *
  3066.   ***************************************************************************/
  3067.  
  3068.   BOOL Addit = FALSE ;
  3069.   BYTE Command = 0 ;
  3070.   BYTE NonRemovable ;
  3071.  
  3072.   ULONG LengthIn = sizeof(Command) ;
  3073.   ULONG LengthOut = sizeof(NonRemovable);
  3074.  
  3075.   if 
  3076.   ( 
  3077.     NOT DosDevIOCtl 
  3078.     ( 
  3079.       Handle, 8, 0x20, 
  3080.       &Command, sizeof(Command), &LengthIn,
  3081.       &NonRemovable, sizeof(NonRemovable), &LengthOut 
  3082.     ) 
  3083.   )
  3084.   {
  3085.     Addit = NonRemovable ;
  3086.   }
  3087.  
  3088.  /***************************************************************************
  3089.   * Close the drive.                                *
  3090.   ***************************************************************************/
  3091.  
  3092.   DosClose ( Handle ) ;
  3093.  
  3094.  /***************************************************************************
  3095.   * Return the final verdict.                            *
  3096.   ***************************************************************************/
  3097.  
  3098.   return ( Addit ) ;
  3099. }
  3100.  
  3101. /****************************************************************************
  3102.  *                                        *
  3103.  *             Calibrate the Load Meter                *
  3104.  *                                        *
  3105.  ****************************************************************************/
  3106.  
  3107. STATIC ULONG CalibrateLoadMeter ( void )
  3108. {
  3109.  /***************************************************************************
  3110.   * Set result to zero as a default.                        *
  3111.   ***************************************************************************/
  3112.  
  3113.   double AdjustedMaxLoad = 0.0 ;
  3114.  
  3115.  /***************************************************************************
  3116.   * If HRTIMER.SYS has been installed . . .                    *
  3117.   ***************************************************************************/
  3118.  
  3119.   if ( OpenTimer ( ) )
  3120.   {
  3121.    /*************************************************************************
  3122.     * Increase this thread's priority to the maximum.                       *
  3123.     *************************************************************************/
  3124.  
  3125.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 ) ;
  3126.  
  3127.    /*************************************************************************
  3128.     * Create the calibration thread and set its priority next highest.        *
  3129.     *************************************************************************/
  3130.  
  3131.     TID tidCalibrate ;
  3132.     ULONG MaxLoad ;
  3133.     DosCreateThread ( &tidCalibrate, CounterThread, (ULONG)&MaxLoad, 0, 4096 ) ;
  3134.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, tidCalibrate ) ;
  3135.     DosSuspendThread ( tidCalibrate ) ;
  3136.  
  3137.    /*************************************************************************
  3138.     * Reset the calibration count, get the time, and let the counter go.    *
  3139.     *************************************************************************/
  3140.  
  3141.     MaxLoad = 0 ;
  3142.     TIMESTAMP Time[2] ;
  3143.     GetTime ( &Time[0] ) ;
  3144.     DosResumeThread ( tidCalibrate ) ;
  3145.  
  3146.    /*************************************************************************
  3147.     * Sleep for one second.                            *
  3148.     *************************************************************************/
  3149.  
  3150.     DosSleep ( 1000 ) ;
  3151.  
  3152.    /*************************************************************************
  3153.     * Suspend the calibration counter and get the time.             *
  3154.     *************************************************************************/
  3155.  
  3156.     DosSuspendThread ( tidCalibrate ) ;
  3157.     GetTime ( &Time[1] ) ;
  3158.  
  3159.    /*************************************************************************
  3160.     * Return priorities to normal.                        *
  3161.     *************************************************************************/
  3162.  
  3163.     DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, 0 ) ;
  3164.  
  3165.    /*************************************************************************
  3166.     * Get the elapsed time and adjust the calibration count.            *
  3167.     *************************************************************************/
  3168.  
  3169.     ULONG Milliseconds ;
  3170.     ULONG Nanoseconds ;
  3171.     Milliseconds = ComputeElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  3172.  
  3173.     AdjustedMaxLoad = (double)MaxLoad * 1.0E9 ;
  3174.     AdjustedMaxLoad /= (double)Milliseconds*1.0E6L + (double)Nanoseconds ;
  3175.  
  3176.    /*************************************************************************
  3177.     * Close down the connection to HRTIMER.SYS.                 *
  3178.     *************************************************************************/
  3179.  
  3180.     CloseTimer ( ) ;
  3181.   }
  3182.  
  3183.  /***************************************************************************
  3184.   * Return the adjusted calibration count.  If HRTIMER was not there, it    *
  3185.   *   will be zero.                                *
  3186.   ***************************************************************************/
  3187.  
  3188.   return ( (ULONG)AdjustedMaxLoad ) ;
  3189. }
  3190.  
  3191. /****************************************************************************
  3192.  *                                        *
  3193.  *              General Purpose Counter Thread                *
  3194.  *                                        *
  3195.  ****************************************************************************/
  3196.  
  3197. STATIC VOID CounterThread ( ULONG Parameter )
  3198. {
  3199.   PULONG Counter = PULONG ( Parameter ) ;
  3200.  
  3201.   while ( 1 )
  3202.   {
  3203.     (*Counter) ++ ;
  3204.   }
  3205. }
  3206.  
  3207. /****************************************************************************
  3208.  *                                        *
  3209.  *    Open the Profile                            *
  3210.  *                                        *
  3211.  ****************************************************************************/
  3212.  
  3213. STATIC HINI OpenProfile ( PSZ Name, HAB Anchor, HMODULE Library, HWND HelpInstance )
  3214. {
  3215.  /***************************************************************************
  3216.   * Query the system INI for the profile file's path.                       *
  3217.   ***************************************************************************/
  3218.  
  3219.   PSZ ProfilePath = NULL ;
  3220.   ULONG Size ;
  3221.  
  3222.   if ( PrfQueryProfileSize ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"), &Size ) )
  3223.   {
  3224.     // The info exists.  Fetch it.
  3225.     ProfilePath = PSZ ( AllocateMemory ( Size ) ) ;
  3226.     PrfQueryProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3227.       ProfilePath, &Size ) ;
  3228.  
  3229.     // Build the profile file name.
  3230.     BYTE FullPath [_MAX_PATH] ;
  3231.     strcpy ( PCHAR(FullPath), PCHAR(ProfilePath) ) ;
  3232.     strcat ( PCHAR(FullPath), "\\" ) ;
  3233.     strcat ( PCHAR(FullPath), PCHAR(Name) ) ;
  3234.     strcat ( PCHAR(FullPath), ".INI" ) ;
  3235.  
  3236.     // Clean the name up and expand it to a full path.
  3237.     BYTE Path [256] ;
  3238.     DosQueryPathInfo ( FullPath, FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3239.  
  3240.     // Does the file exist?  If not, discard the name.
  3241.     FILESTATUS3 Status ;
  3242.     if ( DosQueryPathInfo ( Path, FIL_STANDARD, &Status, sizeof(Status) ) )
  3243.     {
  3244.       FreeMemory ( ProfilePath ) ;
  3245.       ProfilePath = NULL ;
  3246.     }
  3247.   }
  3248.  
  3249.  /***************************************************************************
  3250.   * If the profile file couldn't be found, ask the user for a path.         *
  3251.   ***************************************************************************/
  3252.  
  3253.   if ( ProfilePath == NULL )
  3254.   {
  3255.     // Set the default path.
  3256.     BYTE Path [256] ;
  3257.     DosQueryPathInfo ( PSZ("."), FIL_QUERYFULLNAME, Path, sizeof(Path) ) ;
  3258.  
  3259.     // Call up the entry dialog.
  3260.     PROFILE_PARMS Parms ;
  3261.     Parms.id = IDD_PROFILE_PATH ;
  3262.     Parms.hwndHelp = HelpInstance ;
  3263.     Parms.Path = Path ;
  3264.     Parms.PathSize = sizeof(Path) ;
  3265.     if ( WinDlgBox ( HWND_DESKTOP, HWND_DESKTOP, PFNWP(ProfileProcessor),
  3266.       Library, IDD_PROFILE_PATH, &Parms ) )
  3267.     {
  3268.       // If OK, save the approved path in the system profile.
  3269.       ProfilePath = PSZ ( AllocateMemory ( strlen(PCHAR(Path)) + 1 ) ) ;
  3270.       strcpy ( PCHAR(ProfilePath), PCHAR(Path) ) ;
  3271.  
  3272.       PrfWriteProfileData ( HINI_USERPROFILE, PSZ(PROGRAM_NAME), PSZ("INIPATH"),
  3273.     ProfilePath, strlen(PCHAR(ProfilePath))+1 ) ;
  3274.     }
  3275.     else
  3276.     {
  3277.       // If not, return an error.
  3278.       return ( NULL ) ;
  3279.     }
  3280.   }
  3281.  
  3282.  /***************************************************************************
  3283.   * Build the full profile file name.                        *
  3284.   ***************************************************************************/
  3285.  
  3286.   BYTE ProfileName [_MAX_PATH] ;
  3287.   strcpy ( PCHAR(ProfileName), PCHAR(ProfilePath) ) ;
  3288.   strcat ( PCHAR(ProfileName), "\\" PROGRAM_NAME ".INI" ) ;
  3289.  
  3290.  /***************************************************************************
  3291.   * Release the memory previously allocated to store the path.            *
  3292.   ***************************************************************************/
  3293.  
  3294.   if ( ProfilePath )
  3295.   {
  3296.     FreeMemory ( ProfilePath ) ;
  3297.   }
  3298.  
  3299.  /***************************************************************************
  3300.   * Open/Create the profile file and return the resultant handle.        *
  3301.   ***************************************************************************/
  3302.  
  3303.   return ( PrfOpenProfile ( Anchor, ProfileName ) ) ;
  3304. }
  3305.